Will this close/dispose properly?

  • Thread starter Thread starter Daniel Billingsley
  • Start date Start date
D

Daniel Billingsley

Given that
- The CloseConnection CommandBehavior of ExecuteReader causes the connection
to be "closed" when the DataReader is closed
- Close and Dispose are interchangeable on these ADO objects

1) Will the connection object in the following code get closed/disposed?

2) Since it's created in the static method of the DataFactory class but
referenced by the DataReader in the BusinessObject class, how would you
describe the scope of the connection object?

Wait - variables have scope, not objects in memory, right? So it will be
referenced both by the DataReader in the BusinessObject and the variable cn
within the scope of the GetDataReader method, right? We know when the cn
reference goes away, of course... so when the DataReader is closed then the
connection will also be closed and all will be right in the GC world.
Yes???

If possible, can you enlighten me on how you'd go about testing such a
thing, if it's possible. The DataReader doesn't expose any information
about the connection so it can't be checked through the back door that way.

============

class BusinessObject
{
public ReadData
{
using (SqlDataReader dr = DataFactory.GetDataReader()) // has some
parameters in reality
{
// extract the data from the datareader here
}
}
}

class DataFactory
{
public static SqlDataReader GetDataReader() // takes some parameters in
reality
{
SqlDataReader dr = null;
SqlConnection cn = new SqlConnection(); // with necessary parameters
cn.Open();
using (SqlCommand cm = new SqlCommand()) // with necessary parameters
{
// Set up command object
dr = cm.ExecuteReader(CommandBehavior.CloseConnection);
}
return dr;
}
}
 
Hi Daniel,

Yes, the connection is closed when the Dispose/Close method is called on the
DataReader. I have taken the libety of including a summary description of
the key point that occur in the code.

The SqlConnection is allocated on the managed heap, so regardless of if it
was allocated by a call to a static or non-static method the object exists
on the heap and as long as it is reacheable it will not be elligeable for
collection. Since you are returning the DataReader from the GetDataReader
method, the connection is still reacheable via the reference to the Command
object which is held by the DataReader. In the case of
CommandBehaviour.CloseConnection when the DataReader is disposed at the end
of the using statement, the Connection is closed and the reference to the
Command is set to null. At this point neither the Command object nor the
Connection object are reacheable and are elligeable for collection. Of
cource since you are no longer referencing the DataReader it is also
elligeable for collection, however even if you mantained the reference to
the DataReader, the Command and Connection object are no longer reacheable
since the only surviving reference was that in the DataReader and that has
been set to null.

The best way to verify these things is to use ILDASM and take a look at what
the code is doing internally.

Hope this helps
 
Do I understand you to be suggesting that the command is not really disposed
by the using{} in the static factory: "the connection is still reacheable
via the reference to the Command object which is held by the DataReader"

Not only would I find that odd that the compiler decides the using{} will
not really work the way I expect, but also doesn't seem consistent with the
fact that if I put a using{} around the connection in the static factory I
get an error in the BO saying I can't use the DataReader on a closed
connection.

I guess my original question might be rephrased to ask if this would be
considered acceptable since I don't explicitly dispose the connection and
rely on the CloseConnection behavior to do so indirectly.
 
Hi,

No, my description describes the sequence of events starting in the static
function. If you notice that when I reach the point in the description where
the using block ends I state the following:

"the DataReader is disposed at the end of the using statement, the
Connection is closed and the reference to the
Command is set to null. At this point neither the Command object nor the
Connection object are reacheable and are elligeable for collection"


Hope this helps
 
That doesn't really answer my question.

The "reference to the Command" that is set to null when the DataReader is
disposed would be referring to a Command that has already been disposed (in
the static function) though, right?
 
That is correct, however calling the dispose method does not make an object
unreacheable so only once the command object is set to null does the memory
allocated for the command object become elegiable for collection. So even
though the command object has been disposed, the managed memory which was
allocated for the object lingers until the DataReader releases its
reference.
 
Back
Top