Close() and Dispose()

  • Thread starter Thread starter alx
  • Start date Start date
A

alx

On some documentation about ADO.NET, I've found that, during the close
of a IDbConnection, is a "best practice" to close a connection with
these lines of code:

connection.Close();
connection.Dispose();

For example, Microsoft Data Access Application Block uses this code to
close connection. Also they call Dispose method for others ADO.NET
objects (Command, DataAdapter).

I'd like to know if it's really necessary to close a Connection always
with this 2 lines of code and call Dispose method for Command or
DataAdapter objects.

Thanks.
 
On some documentation about ADO.NET, I've found that, during the close
of a IDbConnection, is a "best practice" to close a connection with
these lines of code:

connection.Close();
connection.Dispose();

AFAIK, when you dispose a connection object, it closes the connection first,
if it's still open...
 
Generally speaking the Dispose method is a generalization of any method name
which have the scope to signal that the work with the object is finished and
that the object must free all the resources. In the framework the Dispose
method will always call the particular method, with the particular name
which have that purpose (which can be named Close, Free or whatever).

So if a class has the method Dispose call it (you don't need to call the
Close or Free method if you call Dispose).

This interface IDisposable/method Dispose made also possible the "using"
statement.
 
Hi,

Dispose should close connection as well, but main purpose of Dispose not to
close the connection but to release the resources for the unmanaged code
inside of the class. If you do not call Dispose method you could face
situation when resources are not freed until you close your application. It
could lead to the fact when memory will grow and will not be released even
if you do not use objects anymore. Garbage Collector will not release memory
just because it does not know anything about unmanaged resources.
 
Alx.

Angel is always telling us in this newsgroup. That they (MS) have *used* the
dispose from the connection in the framework 1.x to do something with the
connection pooling.
And that it always should be used with the connection.

This is important when there can be more than 100 concurrent connections.
(I have seen that it is true).

This is done in another way he write than in Net 2.0

Normally the dispose is mostly only inherrited from the component class
(which all classes in the system.data namespace do).

I hope this helps,

Cor
 
Sahil Malik said:

Interesting, as always. Below is some sample C# code I found on the net -
from the general consensus of opinion round here, quite a lot of the code in
the finally {...} section appears to be redundant. Specifically:

1) Is it necessary in the finally {...} section to check whether each object
has actually been instantiated (i.e. != null) first?

2) Since the Dispose() methods will close any open connections, presumably
the two Close() sections are completely unnecessary?

3) Is it necessary to set the objects to null after they've been Disposed?
Does this have any effect / value, or is this just a lack of understanding
about ADO.NET and a throwback to ADO classic where the only way to destroy
objects was to Set them to Nothing?


public static int ExecuteSQL(string pstrConnectionString, string pstrSQL)
{
try
{
m_objSqlConn = new SqlConnection(pstrConnectionString);
m_objSqlCommand = new SqlCommand(pstrSQL, m_objSqlConn);
m_objSqlCommand.Connection.Open();
return m_objSqlCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
throw (ex);
}
finally
{
if (m_objSqlCommand != null)
{
if (m_objSqlCommand.Connection.State != ConnectionState.Closed)
{
m_objSqlCommand.Connection.Close();
}
m_objSqlCommand.Dispose();
m_objSqlCommand = null;
}
if (m_objSqlConn != null)
{
if(m_objSqlConn.State != ConnectionState.Closed)
{
m_objSqlConn.Close();
}
m_objSqlConn.Dispose();
m_objSqlConn = null;
}
}
}
 
Here are my views -
1) Is it necessary in the finally {...} section to check whether each
object has actually been instantiated (i.e. != null) first?

What if an exception occurs in the finally block?
2) Since the Dispose() methods will close any open connections, presumably
the two Close() sections are completely unnecessary?

Yes - but some people insist that for "clarity" you should put it there. I
personally don't care.
3) Is it necessary to set the objects to null after they've been Disposed?
Does this have any effect / value, or is this just a lack of understanding
about ADO.NET and a throwback to ADO classic where the only way to destroy
objects was to Set them to Nothing?

Not neccessary.

Say A holds a reference to B. In A's Dispose, B is cleared off. Then in the
following code
{
.....
A.Dispose()
..... Point P
}

Point Q

At Point P --- B is ready to be GC'ed, but not A's reference - maybe all of
A's content, but not the reference itself.
At Point Q --- Both A and B can be GC'ed.

The difference between the two is so little, it doesn't really matter :-/.

- Sahil Malik
http://codebetter.com/blogs/sahil.malik/
 
Uhmm hmm .. not really.

A "Closed" connection's underlying physical connection will be pooled I
think. The big difference between Dispose and Close is - it gets rid of huge
structs that store the state of the SqlConnection, so you can open a closed
connection, but you can't do so with a Disposed.

I believe what Angel has said is "Dispose could be used for more than just
this, but so far it hasn't been - but an attempt was made in 2.0" - but my
memory is hazy here, and I'd rather let angel talk for angel :-).

- Sahil Malik
http://codebetter.com/blogs/sahil.malik/
 
AFAIK - per "Dispose"'s definition - you might be right. But
SqlConnection.Dispose simply forgets the state of the connection and closes
it - which basically returns the still open and available physical
connection back to the pool. So being a purist, strictly speaking - maybe
there are no Unmanaged resources to deallocate in SqlConnection.Dispose -
but those are really managed by the connection pool manager that lies
underneath.

Of course other providers might be different.

Regards "If you do not call Dispose method you could face situation when
resources are not freed until you close your application. " == Again; not
necessarily. Objects that fall out of scope will eventually be finalized.
Even though your appdomain hasn't exited yet. Dispose is just better ;).

Regards "Garbage Collector will not release memory just because it does not
know anything about unmanaged resources.". This depends heavily on what
unmanaged resource we are talking about, and how does your .NET class use
it.

- Sahil Malik
http://codebetter.com/blogs/sahil.malik/
 
Sahil,

As I said I have seen this behaviour, because there was somebody who had
problems with more than 100 connections. He changed his close to dispose and
his problems where gone.

Can be a coinsidence. However although a lot have written as you, (including
me; the documentation says that the dispose deletes only (as it is an
overrided method) the connection string).

I have said that I follow Angel in this until is *proven* that he is wrong.

Cor
 
Close() and Dispose() are basically the same thing on an ADO.NET connection
object for providers shipped by Microsoft, and typically for 3rd party
providers as well (haven't seen one that does it differently, but you never
know :). The only difference is that Dispose also clears the connection
string. Calling only 1 of them is enough - whichever you prefer or applies
more to your scenario (e.g. C# "using" statement calls Dispose).

--
Pablo Castro
Program Manager - ADO.NET Team
Microsoft Corp.

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Pablo,

Per reflector --
protected override void Dispose(bool disposing)
{
if (disposing)
{
this._userConnectionOptions = null;
this._poolGroup = null;
this.Close();
}
base.Dispose(disposing);
}

_userConnectionOptions and _poolGroup seem to have more than just
"connection string" as a string, but I am sure that is what you meant
effectively speaking anyway.

- Sahil Malik
http://codebetter.com/blogs/sahil.malik/
 
Hi Sahil,

Sure, I simplified things a little bit :)

_userConnectionOptions is effectively the processed connection string as the
provider uses it internally. Setting the poolgroup to null has no noticeable
effect on the API behavior.

--
Pablo Castro
Program Manager - ADO.NET Team
Microsoft Corp.

This posting is provided "AS IS" with no warranties, and confers no rights.
 
Pablo,

Thanks this makes the impossible (it seems forever) during discussion again
more understandable.

:-)

Cor
 
I agree with Cor. I have also seen situations in which dispose ends up in
not freeing up connection.

This only happens when connection count grows to 100.

Close works perfect with this. So there must be something different with
both of them.


zahmed.
 
Zulifiqar,
This only happens when connection count grows to 100.

Close works perfect with this. So there must be something different with
both of them.

There should be a misunderstanding between us.

Angel tells forever to use dispose for this, and now what Pablo writes makes
it more clear for me why there is written about the connection string. I now
understand that I was reading the by the programmer set connection String
and Pablo and Angel mean the internal connection string.

I have seen by a person in this or another newsgroup that changing his
connection.close to connection.dispose solved his problem with the plus 100
connections.

He did constructing and disposing it everytime when a connection was
needed..

Just to make it clear, nothing wrong.

Cor
 
Back
Top