I'm still relatively new to C# and have only within the past several days been exposed to "IDisposables". I can grasp the concept of the using block to take care of objects which must be disposed of without needing to manually remember to call the .Dispose() method - convenient!
Let's say though that I start with a new SqlConnection which I handle within a using statement. Within that block of code I create some additional IDisposables, for example a SqlDataAdapter. Does that adapter need it's own using statement?
For example, if I have code...
using (SqlConnection myConnection = new SqlConnection())
{
SqlCommand myCommand = new SqlCommand();
SqlDataAdapter myAdapter = new SqlDataAdapter();
// Do things
}
... will myCommand and myAdapter be disposed of when myConnection is disposed (since they are within the scope of that code block)? Or do I need multiple using statements, maybe something like:
using (SqlConnection myConnection = new SqlConnection())
{
using (SqlCommand myCommand = new SqlCommand())
{
using (SqlDataAdapter myAdapter = new SqlDataAdapter())
{
// Do things
}
}
}
Strictly speaking, it would indeed be best to dispose all of them. However, you can avoid the indenting by nesting them directly:
using (var myConnection = new SqlConnection())
using (var myCommand = new SqlCommand())
using (var myAdapter = new SqlDataAdapter())
{
// Do things
}
Alternatively, specifically in the case of ADO.NET (which does, let's be fair, have a lot of disposable types), you might find it easier to use one of the libraries that hides away a lot of the plumbing - for example, with "dapper":
using(var conn = new SqlConnection(...))
{
return conn.Query<Customer>(
"select * from Customers where Region=#region",
new { region }).ToList();
}
Does that adapter need it's own using statement?
In this case, no. But that depends on detailed knowledge of the Connection and Adapter objects so as a best practice: use one using() per IDisposable. Even for MemoryStream where Dispose() does nothing. They are inexpensive.
Your code is correct but we usually economize on the {} :
using (SqlConnection myConnection = new SqlConnection())
using (SqlCommand myCommand = new SqlCommand())
using (SqlDataAdapter myAdapter = new SqlDataAdapter())
{
// Do things
}
We use the rule here that when a using() controls 1 statement (the next using()), you don't need braces. And then we fudge on the indentation a little.
Using is just syntatic sugar for
var connection = new Connection();
try
{
connection.DoSomething();
}
finally
{
// Check for a null resource.
if (connection != null)
{
((IDisposable)connection).Dispose();
}
}
So yes, you need nested using statements to be sure to dispose all of these
Related
I would like to refactor my SqlDataReader code, so it's using using..
SqlDataReader reader = null;
reader = xdCmd.ExecuteReader();
// use reader..
Can I use solution 1) where I declare the reader in the using and first later initialize it with a SqlDataReader, and still get the Dispose "features" using provides? Or do I need to do it as in solution 2), where the initialization happends right away, in the using?
I would guess that 1) is fine, but I'm not sure.
1)
using (SqlDataReader reader = null)
{
xdCmd.CommandText = $"select * from {tableName}";
reader = xdCmd.ExecuteReader();
// use reader..
}
2)
using (SqlDataReader reader = new SqlDataReader(new SqlCommand($"select * from {tableName}"), xdCon))
{
reader = xdCmd.ExecuteReader();
// use reader..
}
The C# language does not include syntax to express the concept of object "ownership" or lifetime management unlike Rust, so it's entirely up to an API's documentation to say if an object's constructor takes ownership of its arguments or not (and thus who gets to call .Dispose()). This is not something the C# compiler can determine for you. However .Dispose() implementations must be idempotent anyway so there is no harm in calling .Dispose() multiple (redundant) times.
Just follow the C# idiomatic conventions of stacked using statements:
using( SqlConnection c = new SqlConnection( connectionString ) )
using( SqlCommand cmd = c.CreateCommand() )
{
await c.OpenAsync().ConfigureAwait(false);
cmd.CommandText = "SELECT foo, bar FROM baz";
using( SqlDataReader rdr = await cmd.ExecuteReaderAsync().ConfigureAwait(false) )
{
...
}
}
for me i prefere to use the second solution it's more subtle , or you can use my example just below :
using (var sqlConnection = new SqlConnection(connection))
{
using (var command = new SqlCommand(query, sqlConnection))
{
using (var read = command.ExecuteReader())
{
// process on your read
}
}
}
i took this code from msdn
string connString = "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;";
using (SqlConnection conn = new SqlConnection(connString))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT CustomerId, CompanyName FROM Customers";
conn.Open();
using (SqlDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
Console.WriteLine("{0}\t{1}", dr.GetString(0), dr.GetString(1));
}
}
as you can see there is no using for the SqlCommand here, so, does it needs to be ?
You need a using for every object you create that implements IDisposable. That includes the SqlCommand and the SqlConnection.
There are very few exceptions to this rule. The main exception is WCF client proxies. Due to a design flaw, their Dispose method can sometimes throw an exception. If you used the proxy in a using statement, this second exception would cause you to lose the original exception.
You don't NEED to use a using statement, but it is good practice and you SHOULD use it. It allows objects using IDisposable to be disposed of automatically.
http://msdn.microsoft.com/en-us/library/yh598w02(VS.80).aspx
Edited to add link and remove inaccurate statement because #John Saunders is right.
Because SqlCommand implements IDisposable, I would normally approach an ADO query as follows.
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(query, connection))
{
// Execute command, etc. here
}
However, what if I need to execute multiple commands during a single connection? Do I really need a new using block for each command?
The examples I found from Microsoft don't use a using block for SqlCommands (or even call Dispose()). What are best practices regarding disposing SqlCommand?
Sure, best practice is to dispose them.
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command1 = new SqlCommand(query1, connection))
{
// Execute command, etc. here
}
using (SqlCommand command2 = new SqlCommand(query2, connection))
{
// Execute command, etc. here
}
using (SqlCommand command3 = new SqlCommand(query3, connection))
{
// Execute command, etc. here
}
}
MSDN probably doesn't show it because it's not really needed in case of SqlCommand. But in my opinion it's bad from microsoft to not use this pattern on every object that implements IDdisosable because people aren't getting used to it.
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block.
In this case you use using for each command block:
using (SqlConnection connection = new SqlConnection(connectionString))
{
using (SqlCommand cmd1= new SqlCommand(query1, connection))
{
}
using (SqlCommand cmd2= new SqlCommand(query2, connection))
{
}
}
No you do not. There are 2 ways that your multiple commands could be bundled within one connection and command.
The first would be to just reuse the existing CMD object, but changing the CommandText and other CMD.properties as needed.
using (SqlConnection con = new SqlConnection(connectionString)) {
con.Open();
using (SqlCommand cmd = new SqlCommand(query1, con)) {
// cmd.CommandType = CommandType.xxxxx
// add any parameters
// Execute()
cmd.CommandText = query2;
// reset CommandType if needed
// adjust parameters if needed
// Execute()
cmd.CommandText = query 3;
// reset CommandType if needed
// adjust parameters if needed
// Execute()
}
con.Close();
}
The second method would be to create a Stored Procedure on the database server and call that in the one CMD object
-- Database
CREATE PROCEDURE schema.sproc_CommandBatch (
-- any variables here
) AS
BEGIN
-- query 1
-- query 2
-- query 3
END
GO
// C#
using (SqlConnection con = new SqlConnection(connectionString)) {
con.Open();
using (SqlCommand cmd = new SqlCommand("schema.sproc_CommandBatch", con)) {
// cmd.CommandType = CommandType.StoredProcedure
// add any parameters
// Execute()
}
con.Close();
}
Best practice is that if it implements IDisposable then Dispose() it. In fact the examples here do all call Dispose. With a wrinkle:
The first example, where it opens a SqlDataReader, calls .Close() on the command in the finally clause. In fact, .Close is just a wrapper around .Dispose() (and no longer appears in the documentation). Jonathan Wood in his comment pointed out that the Close is on the reader. This is wrong.
For multiple calls on the same connection you can:
Re-use the one command (declared in one using). I don't like this
myself, but that's just me: I find it...ugly.
Use multiple commands in multiple usings. That's what I'd do.
'Best Practice' is a bit amorphous. There's never unanimous agreement that what person A touts as Best Practice is better than what person B is recommending, let alone C, D or E. Use your own judgement.
I've only recently learned about this mechanism of connection pooling and discovered that I had been coding my SQL connections all wrong. I used to maintain a global SQL connection against which all SqlCommands would execute.
So I'm now making large scale changes to my existing code. There were no fewer than 260 SqlCommands referencing the global SqlConnection which I am now busy wrapping with
using (SqlConnection sqlConnection = new SqlConnection(globally_stored_connection_string))
{
sqlConnection.Open();
// SqlCommand comes here
}
I suppose it's still a bit of a paradigm shift I have to make, this business of closing a connection only to open a new one shortly after, trusting the connection pooling to take care of the overhead. With that in mind I need to decide now how to wrap SqlCommands that are called many times inside a loop. Would appreciate your thought on which of the following sections of code are preferred (of course there's much more to my SqlCommands than just this but these are simple examples to illustrate the question).
OPTION A:
using (SqlConnection sqlConnection = new SqlConnection(connection_string))
{
foreach(int number in numberList)
{
using (SqlCommand sqlCommand = new SqlCommand("SQL code here using number from foreach loop", sqlConnection))
{
sqlConnection.Open();
sqlCommand.ExecuteNonQuery();
}
}
}
OPTION B:
foreach (int number in numberList)
{
using (SqlConnection sqlConnection = new SqlConnection(connection_string))
{
sqlConnection.Open();
using (SqlCommand sqlCommand = new SqlCommand("SQL code here using number from foreach loop", sqlConnection))
{
sqlCommand.ExecuteNonQuery();
}
}
}
I think you are missing Option C, which to me would make the most sense:
using (SqlConnection sqlConnection = new SqlConnection(connection_string))
{
sqlConnection.Open();
using (SqlCommand sqlCommand = new SqlCommand("SQL code here using number from foreach loop", sqlConnection))
{
foreach (int number in numberList)
{
//Modify command parameters if needed
sqlCommand.ExecuteNonQuery();
}
}
}
This has the least overhead for executing commands. Constructing a SqlCommand object isn't very expensive, but it isn't free either. Here we can reuse it, if possible.
I would go for
using (SqlConnection sqlConnection = new SqlConnection(connection_string))
{
sqlConnection.Open();
foreach(int number in numberList)
{
using (SqlCommand sqlCommand = new SqlCommand("SQL code here using number from foreach loop", sqlConnection))
{
sqlCommand.ExecuteNonQuery();
}
}
}
You only need to open the connection once in this block of code.
While it's good to close the connection as soon as you're done with it, you don't have to take it to the extreme and open a connection for each transaction. It's enough to open it once if your executing several commands one after another. Even with connection pooling there is some overhead in opening a new connection. It's enough if you don't keep it for too long.
I know that a lot of examples exist where a SqlConnection is defined and then a SqlCommand is defined, both in Using blocks:
using (var conn = new SqlConnection(connString)) {
using (var cmd = new SqlCommand()) {
cmd.Connection = conn;
//open the connection
}
}
My question: If I define the connection directly on the SqlCommand, does the connection close when the command is disposed?
using (var cmd = new SqlCommand()) {
cmd.Connection = new SqlConnection(connString);
//open the connection
}
No, SqlCommand never attempts to close/dispose of the connection.
No, the connection object will not be disposed until you dispose it explicitly. But my recommendation is to use using blocks whenever you can.
It does not close the connection, you need to either close it yourself or put it in its own using statment.
Also here is a tip to make your using blocks a bit more readable:
using (var conn = new SqlConnection(connString))
using (var cmd = new SqlCommand())
{
cmd.Connection = conn;
}
#milot
But my recommendation is to use using blocks whenever you can.
Using Using Blocks is nice but useless when working with non IDisposable Objects and so this can be confusing if you use Using Blocks anywhere.
Be careful since your objects might not being Disposed if they don't implements IDisposable.
Hope this helps.