views:

1415

answers:

7

I understand that if I instantiate a SqlConnection object, I am really grabbing a connection from a connection pool. When I call Open(), it will open the connection. If I call the Close() or Dispose() method on that SqlConnection object, it is returned to the connection pool.

However, that doesn't really tell me if it's really closed, or if I still have an active connection to the database.

How can I force a SqlConnection to close at the network level, or at least tell when it closes?

Example:

using(SqlConnection conn = new SqlConnection(DBConnString)) {

   conn.Open();
   SqlCommand cmd = conn.CreateCommand();
   ...
   cmd.ExecuteReader(CommandBehavior.CloseConnection);
   ...
}
  • First run: 300 ms
  • Second run: 100 ms
  • Third run: 100 ms
  • After waiting a long time (30 minutes): 300 ms

If the connection was TRULY closing, the second and third runs should also be 300 ms. But I know that the connection is not truly closed for those runs (I checked the SQL Server's activity monitor). It doesn't take the extra 200ms to perform authentication/etc.

How do I force the connection to truly close?

Ideas

  • Does CommandBehavior.CloseConnection work? (apparently not?)
  • Does setting "Max Pool Size = 0" in the connection string work? (this would be a pyrrhic solution)
  • Does Dispose() work?

References

A: 

use "using"

for example, in C#

using(var myConnection = new SqlConnection())    
{    
    //your code here   
}

http://msdn.microsoft.com/en-us/library/yh598w02%28VS.80%29.aspx

alex
-1 Nothing to do with connection pooling
Ian Boyd
well, it is really -wrap your connection in a using statement - when it's done, it closes and disposes it.http://davidhayden.com/blog/dave/archive/2005/01/13/773.aspx
alex
Except, if you're using connection pooling, the connection is not really closed (or disposed) when you call Close() or Dispose() - that's the entire point of this question/thread.
Tao
Please see this:http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.aspx"To ensure that connections are always closed, open the connection inside of a using block, as shown in the following code fragment. Doing so ensures that the connection is automatically closed when the code exits the block. "It does somewhat contradict itself in the statement above that however
alex
+1  A: 

CommandBehavior.CloseConnection is usually discouraged because of this very fact - You can't be sure that the Connection will be closed. (I'll try to find some concrete evidence of this, I'm saying this from faint recall).

Dispose() is the surest way because it implicitly calls Close().

The using construct demonstrated by @Alex is just another (programmer friendly) way of writing the try-finally construct with the added implicit Disposal of objects.

Edit: (after edit to question)

Your concern over the connections actually closing seems unwarranted to me. The connection would simply return to the pool so that it can be reused easily without having to go through all the initialization. This does not mean that the Connection is still actively connected to the DB.

Cerebrus
A connection in the pool **does** mean it is still activly connected to the DB. For example you can close a Connection object, and you'll still have a shard database lock due to the connection still being in the pool (http://stackoverflow.com/questions/520716/ado-net-sqlserver-how-to-prevent-closed-connection-from-holding-s-db-lock)
Ian Boyd
+1  A: 

This is what I do. It hasn't failed for me yet...

SqlConnection conn;

try
{
  conn = new SqlConnection(DBConnString);
  conn.Open();
  SqlCommand cmd = conn.CreateCommand();
  ...
  cmd.ExecuteReader();
}
catch (Exception ex)
{
  ...   
}
finally
{
  if (conn != null && conn.State != ConnectionState.Closed)
    conn.Close();
}
Steve Wortham
+4  A: 

If you don't want to use the connection pool you have to specify it in your SqlConnection.ConnectionString property (example "Data Source=MSSQL1;Database=AdventureWorks;Integrated Security=true;Pooling=false;")

Disposing or closing the SqlConnection object is just going to close the connection and return it to the connectionpool.

ZippyV
+9  A: 

Maybe SqlConnection.ClearPool ?

Moe Sisko
+1 for the first responder to read the question properly.
Joe
+2  A: 

Generally, you want the connection pool to do its job - you don't want the connection to truly close.

Why specifically do you want the connection not to return to the pool?

Eamon Nerbonne
A connection in the pool can will hold locks.
Ian Boyd
I'm not sure what kind of locks you're referring too - a disposed connection whose underlying connection is returned to the connection pool should not be participating in any transactions or holding any locks relevant to consuming code. Of course it's still using a network port and a few other resources - but the very acquisition cost of these resources is *why* you *don't* what to free them. Unless you're trying to delete/restore the underlying database or something similarly radical, these locks aren't problematic.
Eamon Nerbonne
+5  A: 

Moe Sisko's answer (Call SqlConnection.ClearPool) is correct.

Sometimes you need a connection to really close rather than return to the pool. As an example, I have a unit test that creates a scratch database, builds the schema, tests some stuff, then drops the scratch database if the tests all pass.

When connection pooling is active, the drop database command fails because there are still active connections. From the point of view of programmer all SQLConnections are closed, but as the pool still holds one open, SQL Server won't allow the drop.

The best documentation for how connection pooling is handled is this page on SQL Server Connection Pooling on MSDN. One doesn't want to turn connection pooling off entirely because it improves performance with repeated opens and closes, but sometimes you need to call a "force close" on an SQLConnection so that it will let go of the database.

This is done with ClearPool. If you call SQlConnection.ClearPool(connection) before closing/disposing, when you do close/dispose it will really go away.

Robert Calhoun
The use case you describe is almost exactly what I was doing - testing performance of certain db access patterns, using "cold" procedure/data caches and of course, connections.
Jeff Meatball Yang
The link you provide has been added to the question text. Thanks.
Jeff Meatball Yang