We are always hearing that we should dispose of a database connection rather than just closing it because a database connection is an unmanaged resource (SqlConnection, OledbConnection, OdbcConnection). So you would think the following code makes sense:
using(SqlConnection con= new SqlConnection())
{
//open database conncetion
//do database transaction
//close connection
con.Close();
}
1:
2:
3:
4:
5:
6:
7:
Select allOpen in new window
At first glance it looks like nice, clean code. We are closing all the resources we are opening as well as disposing (the using block will make sure that Dispose will be called for con object) the same to make sure there will be no memory leaks.
But when we go inside SqlConnection.Dispose() method using reflector, we find that we are again calling the same Close() method.
protected override void Dispose(bool disposing)
{
if (disposing)
{
this._userConnectionOptions = null;
this._poolGroup = null;
this.Close();
}
this.DisposeMe(disposing);
base.Dispose(disposing);
}
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
Select allOpen in new window
Dispose is doing much more than simply closing the connection, – like making _poolGroup null. So the better approach to managing connections is:
using(SqlConnection con= new SqlConnection())
{
//open database conncetion
//do database transaction
//close connection
}
1:
2:
3:
4:
5:
6:
Select allOpen in new window
Now the Dispose() method will make sure that connection will be closed.
In addition, if we are simply calling con.Close(), as Close() we will leave the connection to the connection pool which will result in better performance. And then we can use Dispose() to remove the connection from the pool.
Following is the proper implementation of CloseConnection() which is called by the Close() method:
internal virtual void CloseConnection(DbConnection owningObject, DbConnectionFactory connectionFactory)
{
Bid.PoolerTrace("<prov.DbConnectionInternal.CloseConnection|RES|CPOOL> %d# Closing.\n", this.ObjectID);
if (connectionFactory.SetInnerConnectionFrom(owningObject, DbConnectionOpenBusy.SingletonInstance, this))
{
try
{
DbConnectionPool pool = this.Pool;
Transaction enlistedTransaction = this.EnlistedTransaction;
if ((null != enlistedTransaction) && (enlistedTransaction.TransactionInformation.Status != TransactionStatus.Active))
{
this.DetachTransaction(enlistedTransaction);
}
if (pool != null)
{
pool.PutObject(this, owningObject);
}
else
{
this.Deactivate();
this.PerformanceCounters.HardDisconnectsPerSecond.Increment();
this._owningObject.Target = null;
if (this.IsTransactionRoot)
{
this.SetInStasis();
}
else
{
this.PerformanceCounters.NumberOfNonPooledConnections.Decrement();
if (base.GetType() != typeof(SqlInternalConnectionSmi))
{
this.Dispose();
}
}
}
}
finally
{
connectionFactory.SetInnerConnectionEvent(owningObject, DbConnectionClosedPreviouslyOpened.SingletonInstance);
}
}
}
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
Select allOpen in new window
So my take on this is: If performance is not an issue, you can still use Connection.Dispose(). But if you want better performance use the Connection.Close() method I have described.
by: naman_goel on 2010-10-21 at 08:27:32ID: 20685
I looks fine to me.