tags:

views:

797

answers:

2

Hello Everyone,

This is my first post on StackOverflow, so please be gentle...

I have some questions regarding object scope for ADO.NET.

When I connect to a database, I typically use code like this:

OleDbConnection conn = new OleDbConnection("my_connection_string");
conn.Open();
OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn);
OleDbCommandBuilder cb = new OleDbCommandBuilder(adapter);
DataTable dt = new DataTable();
adapter.Fill(dt);
conn.Close();
conn.Dispose();

Let's say that I bind the resulting DataTable to a grid control and allow my users to edit the grid contents. Now, when my users press a Save button, I need to call this code:

adapter.Update(dt);

Here are my questions:

1) Do I need to retain the adapter object that I created when I originally loaded the datatable, or can I create another adapter object in the Save button click event to perform the update?

2) If I do need to retain the original adapter object, do I also need to keep the connection object available and open?

I understand the disconnected model of ADO.NET - I'm just confused on object scope when it's time to update the database. If someone could give me a few pointers on best practices for this scenario, I would greatly appreciate it!

Thanks in advance...

+1  A: 

1) You don't need the same DataAdapter, but if you create a new one it must use the same query as its base.

2) The DataAdapter will open its connection if the connection is closed. In that case it will close the connection again after it is done. If the connection is already open it will leave the connection open even after it is done.

Normally you would work as in your example. Create a Conneciton and a DataAdapter, fill a DataTable and dispose of the Connection and the DataAdapter afterwards.

Two comments to your code:

  • You don't need the CommandBuilder here since you only do a select. The command builder is only needed if you want to generate Insert, Update or Delete statements automatically. In that case you also need to set the InsertCommand, UpdateCommand or DeleteCommand on the DataAdapter manually from the CommandBuilder.
  • Second. Instead of calling Dispose manually you should use the Using clause. It ensures that your objects will be disposed of even if an exception is thrown.

Try to change your code to this:

DataTable dt = new DataTable();
using (OleDbConnection conn = new OleDbConnection("my_connection_string"))
using (OleDbDataAdapter adapter = new OleDbDataAdapter("SELECT * from Employees", conn))
{
  adapter.Fill(dt);    
}

Note that I define the DataTable outside the using clauses. This is needed to ensure that the table is in scope when you leave the usings. Also note that you don't need the Dispose call on the DataAdapter or the Close call on the Connection. Both are done implicitly when you leave the usings.

Oh. And welcome to SO :-)

Rune Grimstad
Data adaptors are able to open connections implicitly, now i'm not sure about doing this inside a using statement, but couldn't you just drop the conn.Open() line, and let the dataadaptor open the connection.?
GordonB
Good point. I even mentioned it under 2). :-) I'll update the code example
Rune Grimstad
A: 

To answer your questions:

  1. Ideally, you should retain the same DataAdapter because it has already performed it's initialization. A DataAdapter provides properties such as the SelectCommand, UpdateCommand, InsertCommand and DeleteCommand which allow you to set different Command objects to perform these different function on the datasource. So, you see, the DataAdapter is designed to be reused for multiple commands (for the same database connection). Your use of the CommandBuilder (though, not recommended) creates the other Commands by analysing the SelectCommand, thus allowing you to perform Updates, Deletes and Inserts using the same CommandBuilder.

  2. It is best to allow the DataAdapter to implicitly handle database connections. @Rune Grimstad has already elaborated on this implicit behaviour and it's useful to understand this. Ideally, connections should be closed as soon as possible.

Cerebrus

related questions