using (SqlConnection), scope and connection pooling - c#

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.

Related

Disposing SqlCommand

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.

Is "connection.Close()" the best or safest way to close an SQL connection?

I've been using
connection.Close();
But this is my first project in .NET and I'm not sure if I'm closing it correctly.
I don't want my website to instantly die after putting it out on real hosting.
Usually I do it this way:
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString());
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
// <some code>
conn.Open();
/ <some code>
conn.Close();
You should place the connection in a using statement;
using(var connection = new SqlConnection)
{
connection.Open();
...other code using it here.
}
The using statement ensures that the SqlConnection is disposed when you are done with it. In your scenario (depending on where you put the close method), if an exception is closed, it will never reach the Close() method and the connection will stay open.
Even better is that since you are building a website. There should be a method on the Request object (which should be available) called RegisterForDispose. This will automatically Dispose of the connection (which closes it) when the request ends. You can use it like this:
var connection = new SqlConnection();
Request.RegisterForDispose(connection);
Both accomplish the same thing in the end, but the second allows for more flexibility.
Do what Kevin said and put your .Open() call inside the using block:
using(var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()))
{
var cmd = new SqlCommand("my sql command here", conn);
conn.Open();
cmd.(whatever method you are using)
}

Foreach and SqlConnection Using Statement

I'm trying to figure out which is more efficient to run. I have a foreach of tables and I'm wondering if it should be outside of my using or inside of it. Examples below.
the using (SqlConnection) inside of the foreach:
foreach (string tableName in desiredTables)
{
using (SqlConnection connection = new SqlConnection(cloudConnectionString))
{
connection.Open();
string query = string.Format("SELECT id, active, createdon, modifiedon FROM {0}", tableName);
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
SqlDataAdapter dAdapter = new SqlDataAdapter(cmd);
try
{
dAdapter.Fill(dSet, tableName);
}
catch
{
throw;
}
}
}
}
Versus the foreach inside of the using (SqlConnection):
using (SqlConnection connection = new SqlConnection(cloudConnectionString))
{
connection.Open();
foreach (string tableName in desiredTables)
{
string query = string.Format("SELECT id, active, createdon, modifiedon FROM {0}", tableName);
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = query;
cmd.CommandType = CommandType.Text;
SqlDataAdapter dAdapter = new SqlDataAdapter(cmd);
try
{
dAdapter.Fill(dSet, tableName);
}
catch
{
throw;
}
}
}
}
I'm trying to optimize this for a faster pull from the DB and I'm not sure which way is recommended/better. Advice would be great.
You'll have to try it and measure it to be certain, but I doubt you'll see a huge difference either way. Connections are pooled by .NET, so creating them in a loop (I'm assuming you just have a handful of tables, not several hundred) should not be a significant bottleneck. You'll likely spend a LOT more time in network I/O and actually populating the DataSet (which does have a lot of overhead).
Bottom line - fine one way that works (so you have something to revert back to) and try it multiple ways and see if one method makes a significant difference to the application overall.
Generally, Open and Close a database connection multiple times in a network environment can be expensive (connection data travels thru your network several rounds, the C# CLR has to allocate and free resource several times, the Garbage Collection has more works to do later...), so you should try to reuse your database connection by putting it outside the loop.

Handling IDisposables within another IDisposable "using" statement

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

Does connection close when command is disposed and the connection is defined directly on the command?

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.

Categories