Many people think that the Dispose() method is called internally in the Close() method, so there is no essential difference! In fact, this view is not very accurate.
For some classes, it is true that there is no essential difference between Close() and Dispose(), but for some classes this is not the case!
First, let's look at the difference between the Close() method and Dispose() method of SqlConnection that we use most often:
The Dispose() method of the SqlConnection class is inherited from the Component class. The source code is as follows:
public void Dispose() {
Dispose(true); //Call an overload of Dispose with parameters
GC.SuppressFinalize(this); //Request the system not to call the finalizer of the specified object.
}
protected virtual void Dispose(bool disposing) {
if (disposing) {
lock(this) {
if (site != null && site.Container != null) {
site.Container.Remove(this);
}
if (events != null) {
EventHandler handler = (EventHandler)events[EventDisposed];
if (handler != null) handler(this, EventArgs.Empty);
}
}
}
}
The description of the Close() method of the SqlConnection class in MSDN is as follows:
Close the connection to the database. This is the preferred method of closing any open connection. If the SqlConnection goes out of scope, it will not be closed. because
Therefore, the connection must be closed explicitly by calling Close or Dispose. Close and Dispose are functionally equivalent. If the connection pool value
Pooling If set to true or yes, the underlying connection will be returned to the connection pool. On the other hand, if Pooling is set to false or no, then
The underlying connection to the server is closed.
From the description, it seems that the Close() method and the Dispose() method are similar. In fact, they are only equivalent in the function of closing the connection. Let us take a look at Close.
() method source code:
override public void Close() {
IntPtr hscp;
Bid.ScopeEnter(out hscp, "<sc.SqlConnection.Close|API> %d#" , ObjectID);
try {
SqlStatistics statistics = null;
RuntimeHelpers.PrepareConstrainedRegions();
try {
#if DEBUG
object initialReliabilitySlotValue = Thread.GetData(TdsParser.ReliabilitySlot);
RuntimeHelpers.PrepareConstrainedRegions();
try {
Thread.SetData(TdsParser.ReliabilitySlot, true);
#endif //DEBUG
statistics = SqlStatistics.StartTimer(Statistics);
// The lock here is to protect against the command.cancel / connection.close
race condition
// The SqlInternalConnectionTds is set to OpenBusy during close, once this
what happens the cast below will fail and
// the command will no longer be cancelable. It might be desirable to be
able to cancel the close operation, but this is
// outside of the scope of Whidbey RTM. See (SqlCommand::Cancel) for other
lock.
lock (InnerConnection) {
InnerConnection.CloseConnection(this, ConnectionFactory);
}
// does not require GC.KeepAlive(this) because of OnStateChange
if (null != Statistics) {
ADP.TimerCurrent(out _statistics._closeTimestamp);
}
#if DEBUG
}
finally {
Thread.SetData(TdsParser.ReliabilitySlot, initialReliabilitySlotValue);
}
#endif //DEBUG
}
catch (System.OutOfMemoryException e) {
Abort(e);
throw;
}
catch (System.StackOverflowException e) {
Abort(e);
throw;
}
catch (System.Threading.ThreadAbortException e) {
Abort(e);
throw;
}
finally {
SqlStatistics.StopTimer(statistics);
}
}
finally {
SqlDebugContext sdc = _sdc;
_sdc = null;
Bid.ScopeLeave(ref hscp);
if (sdc != null) {
sdc.Dispose();
}
}
}
You can see that the Close() method does not call the Dispose() method. Although there is a line of sdc.Dispose();, this only releases the SqlDebugContext.
Instance, has nothing to do with the SqlConnection.Dispose() method!
So what's the difference?
The Close() method only closes the connection, and then the connection is stored in the connection pool, so after calling the Close() method, you can still pass
Open() method to open the connection and after calling the Dispose() method, the connection can no longer be used!
Another important difference is that when the Close() method does not call GC.SuppressFinalize(this);, the direct consequence of this is garbage.
Termination operations are required during recycling, which will cause the "generation age" of this instance to increase, thereby greatly delaying the recycling time of this object!
For the SqlConnection class, if you need to use this connection in the future, you can use the Close() method to temporarily close the connection.
To use this connection, you can first use the Dispose() method to release resources. Of course, you can use the using keyword to simplify this process.
I have not found the source code of the OleDbConnection class and the OdbcConnection class, but they should be similar to the SqlConnection class!
Let's look at a commonly used class and see the difference between the Close() method and the Dispose() method of the FileStream class:
The Close() method of the FileStream class is inherited from the Stream class. The source code is as follows:
public virtual void Close()
{
Dispose(true);
GC.SuppressFinalize(this);
}
The Dispose() method of the FileStream class is inherited from the Stream class. The source code is as follows:
public void Dispose()
{
Close();
}
It is an implementation of the standard Dispose mode. The Close() method calls the Dispose method with parameters, and then calls GC.SuppressFinalize.
(this); Requests the system not to call the finalizer of the specified object. The Dispose() method directly calls the Close() method!
For the FileStream class, there is no difference between the Close() method and the Dispose() method!