AllExperts > Experts 
Search      

VB.NET

Volunteer
Answers to thousands of questions
 Home · More Questions · Answer Library  · Encyclopedia ·
More VB.NET Answers
Question Library

Ask a question about VB.NET
Volunteer
Experts of the Month
Expert Login

Awards

About Us
Tell friends
Link to Us
Disclaimer

 
 
 
 
About Chris
Expertise
I can answer pretty much any question relating to VB.NET and its use in a Windows environment. I specialize in ASP.NET web development and MSSQL database access.

Experience
I have over 5 years of industry experience using VB.NET and other .NET technologies for web and database development.

Education/Credentials
I have some college education, but does it really matter in this field of work?

 
   

You are here:  Experts > Computing/Technology > Basic > VB.NET > using table adapters

Topic: VB.NET



Expert: Chris
Date: 8/10/2007
Subject: using table adapters

Question
QUESTION: I have a combobox list of datatable names that I want the user to be able to select from and at the press of a button view the data (possibly in a datagridview table) on a separate form.
In order to 'fill' datagridview you need the table adapter for the specific table you would like to view, but since the user is selecting this it isn't known in advance (the list also contains tables that they might have created and named while using the application)

so far this is what I have for the form where they can preview the data:

Private Sub Preview_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
       previewtable.DataSource =   LobsterDataSetBindingSource ' preview table is the name of the datagridview table
       previewtable.DataMember = CStr(IBM.tablelist.SelectedItem) 'this is the combobox name
       previewtable.AutoGenerateColumns = True
       previewtable.ReadOnly = True
End Sub


any help would be greatly appreciated

Amanda

ANSWER: Since you don't know the details of the table whose data you want to display, you can't ask Visual Studio to generate a data access component for you to use as a data source.  You'll need to access the database through code, but this is actually a good thing.  Direct access using SqlDataAdapter is faster than through those auto generated thingies anyway.

So, the short answer is something like this:

- Add an import for the System.Data.SqlClient namespace to your class by adding this statement to the top of your class:
 Imports System.Data.SqlClient

- Create an SqlConnection to access the database where the table resides.  You'll have to pass it a connection string, telling it which server (eg: 127.0.0.1) and database (eg: Northwind) to work with.  You might also need to provide a username and password - this example assumes your windows user account has the proper rights to access the database:
 Dim conn As New SqlConnection("data source=YOUR_SERVER_NAME;initial catalog=YOUR_DATABASE_NAME;integrated security=SSPI;persist security info=False;packet size=4096")

- Create an SqlCommand to access the table and retrieve its data:
 Dim cmd as New SqlCommand("SELECT * FROM some_table_name", conn)
 
- Create a DataTable to hold the retrieved data, and set its TableName property to the name of the table:
 Dim dt as New DataTable
 dt.TableName = "some_table_name"

- Create and use an SqlDataAdapter to put the data into the DataTable:
 Dim da as New SqlDataAdapter(cmd)
 conn.Open()
 da.Fill(dt)
 conn.Close()

- Set your BindingContainer's DataSource property to this DataTable, then set your DataGridView's DataSource to the BindingContainer (if this wasn't already set in design mode).  Do not set the DataMember property to anything here, or on your DataGridView:
 LobsterDataSetBindingSource.DataSource = dt
 previewtable.DataSource = LobsterDataSetBindingSource

The long answer:

I have created an example application that will demonstrate how to do all of this.  Feel free to reuse and redistribute it as you want.  You can download its source from my website at this URL:
http://www.bl00.net/areas/Gallery/ViewFile.aspx?GalleryFileID=340

Hope this helps!
-Chris


---------- FOLLOW-UP ----------

QUESTION: Thanks for the link, however even when I created a user account I wasn't able to access the gallery section of your website so I haven't been able to view the code.

I tried to do it from the short answer and it didn't work. (my ignorance of VB will show through here). The new tables when/if they are created are saved to the dataset, wouldn't there be an easier way to access them within the application rather then going to the database? If I am saving them on the dataset are they even accessible through the database?
I am also using Microsoft Access so I think I used the wrong server name...where would I find the server name?

thanks
Amanda
(username on your website:vacuit)

Answer
I've fixed the example I posted - you should be able to download it now at the link I gave you - but hold off on that for a minute.

First, I think I should explain that you can not save data into a DataSet, per se.  You can save a DataSet, and its data, to a database (or an XML file, etc.), however.  This is probably what is happening behind your back - I'm assuming this DataSet you're working with was automatically generated by Visual Studio for you, correct?

DataSets are like miniature databases.  You can create tables, add records, modify them, and so forth.  But at some point, you'll have to save this data.  If you're using auto-generated DataSets, they'll only work with the original tables.  Once a table is modified, the DataSet's inner workings which you've been shielded from no longer correspond, and adding or modifying records will probably fail.  You also won't be able to see newly added columns.

Since you're working with tables which the user can apparently create and modify for themselves, automatically generated DataSets (a.k.a. Components, if you're using Visual Studio 2003 or earlier) are no longer an option.  But that's okay, it's always faster executing and easier maintenance to do it manually, believe it or not.

Also, since you're using Microsoft Access, and not MS SQL Server, I should warn you that that example I posted does not completely apply - the method I used to get a list of tables in the database will not work in Access.  Also, some of the code is different - for example you import System.Data.OleDb instead of System.Data.SqlClient to gain access to the database classes.  Instead of using SqlCommand, SqlConnection and SqlDataAdapter, you should use OleDbCommand, OleDbConnection and OleDbDataAdapter.  Fortunately, both use the same SQL queries for inserting, updating and deleting data, so you just need to rename a few things.  Finally, since you're using Access instead of SQL Server, when you create an OleDbConnection, you'll have to pass it a totally different connection string.  It would look something like:
 Dim cmd As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & MyDatabaseFilename)

Now, I said that you can not save data into a DataSet, but you can save a DataSet and its data into a database.  How?  Change the data in code or in a control bound to something in the DataSet (such as a DataGridView), then call the DataAdapter's .Update() command and pass it your DataSet.  But you're going to need to manually instantiate a new DataSet, DataTable and DataAdapter yourself because the user might have created or changed the table themselves.  And to support updating, it has to be done in the correct order, using an OleDbCommandBuilder.  You should also be aware, that since you're not getting those automatically generated DataSets here, you won't be able to access fields from each record as properties directly.  For example if you had a User table with a field called UserName, you'd have to get the DataTable from the DataSet's .Tables property [eg: Dim dt As DataTable = ds.Tables.Item(0)], then get a row to work with, and modify a column [eg: dr.Rows(0).Item("UserName") = "new username"].  But since you'll be working with a DataGridView, it'll handle all of that for you as far as accessing individual rows and the data within.

So, basically you want to:

Create a small class to retrieve a DataSet for any table given in your database.  You'll create a new instance of this, it'll create a DataAdapter, fill a DataTable and put it in a DataSet.  You'll get its result, and bind that DataSet to your BindingContainer, which in turn is bound to your DataGridView.  You'll also want to provide a way to commit changes made to the DataSet to the database, if the DataGridView (or any other bound control) is set to be editable, so that the next time you load data into this DataSet from the database those changes will remain.

So, as you can see, this is not easy.  I'd put the entire resulting class here, but it would look horrible :).  So, I'll update the example - take a look at the TableLoader.vb file in there - you can use it to provide all the synchronization between MS Access and a DataSet.

In case you can't access that, I'll put the key parts here:

' create a connection to your Access .mdb file
Dim conn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & c_strAccessMDBFile)

' this command will retrieve all of the columns from all of the rows of the table specified
Dim cmd As New OleDbCommand("SELECT * FROM " & strTableName, conn)

' this will create a DataAdapter, which synchronizes between DataTables/DataSets and a database
Dim da As New OleDbDataAdapter(cmd)

' create a dataset and a datatable, give the table a name, and add the table to the dataset
Dim ds As New DataSet
Dim dt As New DataTable
dt.TableName = strTableName
ds.Tables.Add(dt)

' open the connection and fill the specified table in the dataset
conn.Open()
da.Fill(ds, strTableName)

' this CommandBuilder will create the necessary Update/Insert/Delete queries for the DataAdapter
Dim cb As New OleDbCommandBuilder(da)
da.InsertCommand = cb.GetInsertCommand()
da.DeleteCommand = cb.GetDeleteCommand()
da.UpdateCommand = cb.GetUpdateCommand()

' always close your connection when done
conn.Close()

' this will allow you to commit changes made to the DataSet back into the database
If ds.HasChanges() Then da.Update(ds)


But like I said, get the updated example I posted, and look at TableLoader.vb - it takes the code from above and wraps it in a class that will keep track of your DataAdapter and DataSet, they're needed together to save changes.

To use it from your code, you'd do something like:

Private Sub Preview_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      Dim objLoader As New TableLoader(CStr(IBM.tablelist.SelectedItem))

      LobsterDataSetBindingSource.DataSource = objLoader.TableDataSet
      LobsterDataSetBindingSource.DataMember = objLoader.TableName

      previewtable.DataSource =   LobsterDataSetBindingSource
      previewtable.AutoGenerateColumns = True
      previewtable.ReadOnly = True
End Sub

Let me know if this works...

Add to this Answer    Ask a Question



  Rate this Answer
   Was this answer helpful?
Not at allDefinitely              
   12345  

     
About Us | Advertise on This Site | User Agreement | Privacy Policy | Help
Copyright  © 2008 About, Inc. About and About.com are registered trademarks of About, Inc. The About logo is a trademark of About, Inc. All rights reserved.