When .NET first came out, I was one of many who complained about .NET\'s lack of deterministic finalization (class destructors being called on an unpredictable schedule). The co
Yes. almost anything in ADO.Net is implementing IDisposable
, whether that's actually needed - in case of, say, SqlConnection
(because of connection pooling) or not - in case of, say, DataTable
(Should I Dispose() DataSet and DataTable?
).
The problem is, as noted in the question:
without understanding the code for each class in some detail, it's hard to be certain which ones I can leave out.
I think that this alone is a good enough reason to keep everything inside a using
statement - in one word: Encapsulation.
In many words: It shouldn't be necessary to get intimately familiar, or even remotely familiar for that matter, with the implementation of every class you are working with. You only need to know the surface area - meaning public methods, properties, events, indexers (and fields, if that class has public fields). from the user of a class point of view, anything other then it's public surface area is an implementation detail.
Regarding all the using
statements in your code - You can write them only once by creating a method that will accept an SQL statement, an Action
and a params array of parameters. Something like this:
void DoStuffWithDataTable(string query, Action action, params SqlParameter[] parameters)
{
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
using (SqlDataAdapter adapter = new SqlDataAdapter(command))
using (SqlCommandBuilder builder = new SqlCommandBuilder(adapter))
using (var table = new DataTable())
{
foreach(var param in parameters)
{
command.Parameters.Add(param);
}
// SqlDataAdapter has a fill overload that only needs a data table
adapter.Fill(table);
action();
adapter.Update(table);
}
}
And you use it like that, for all the actions you need to do with your data table:
DoStuffWithDataTable(
"Select...",
table =>
{ // of course, that doesn't have to be a lambda expression here...
foreach (DataRow row in table.Rows) // search whole table
{
if ((int)row["Id"] == 4)
{
row["Value2"] = 12345;
}
else if ((int)row["Id"] == 5)
{
row.Delete();
}
}
},
new SqlParameter[]
{
new SqlParameter("@FirstValue", 2),
new SqlParameter("@SecondValue", 3)
}
);
This way your code is "safe" with regards of disposing any IDisposable
, while you have only written the plumbing code for that just once.