tags:

views:

144

answers:

3

I usually write my datareader code like this:

        try
        {
            dr = cmd.ExecuteReader(CommandBehavior.SingleResult);
            while (dr.Read())
            {
                //Do stuff
            }
        }
        finally
        {
            if (dr != null) { dr.Close(); }
        }

Is it safe to replace the try/finally w/ just a using block around the DataReader's creation? The reason I wonder is because in all the MS examples I've seen they use a using for the connection but always explictly call Close() on the DataReader.

Heres's an example: http://msdn.microsoft.com/en-us/library/haa3afyz(VS.100).aspx

+3  A: 

Typically, using() calls Dispose() and that calls close() in turn.

In case of a DataReader, the Close is called only when CommandBehavior.CloseConnection is set (see comments of this article http://weblogs.asp.net/joseguay/archive/2008/07/22/ensure-proper-closure-amp-disposal-of-a-datareader.aspx).

EDIT: This article says something interesting:

The Close() method on the SqlDataReader calls an InternalClose() method, which does not call Dispose. Note that previously we stated the correct way to do this was to have your close call dispose. To make it even more confusing the Dispose() method actually calls the Close() method so for this object the order is reversed.

naivists
+1  A: 

Hi there.

From what I can recall, if an exception occurs in a Using block, then the Dispose method is still called on the object. I usually have a Using statement for all disposable objects, without a Try..Catch.

EDIT: Forgot to say that for some objects, calling Dispose will in turn call Close for that object.

Cheers. Jas.

Jason Evans
+2  A: 

Yes. using calls Displose. Calling Dispose on SqlDataReader closes it.

This is psuedo-code of SqlDataReader gleaned from Reflector:

    public void Dispose()
    {
        this.Close();
    }

    public override void Close()
    {
        if( !IsClosed )
            CloseInternal(true);
    }

    private void CloseInternal(bool closeReader)
    {
        try
        {
            // Do some stuff to close the reader itself
        }
        catch(Exception ex)
        {
            this.Connection.Abort();
            throw;
        }

        if( this.Connection != null && CommandBehavior.CloseConnection == true )
        {
            this.Connection.Close();
        }
    }
Greg

related questions