Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check state before disposing SqlTransaction

Tags:

c#

.net

ado.net

I have following code that uses SqlTransaction. I have called dispose in catch and finally blocks.. But I have not checked whether it is already disposed before calling Dispose(). How can we check whether the SqlTransaction is already disposed before calling Dispose()?

I have referred MSDN:SqlTransaction.Dispose Method. But that does not cover my question.

Also referred http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction.dispose(v=vs.100).aspx

Note: I already know that TransactionScope has advantages over SqlTransaction. But I am trying to understand the SqlTransaction’s dispose.

CODE

 using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();

            SqlTransaction transaction = null;

            try
            {
                transaction = connection.BeginTransaction();

                sessionID = GetSessionIDForAssociate(connection, empID, transaction);
                //Other code

                //Commit
                transaction.Commit();
            }
            catch
            {
                //Rollback
                if (transaction != null)
                {
                    transaction.Rollback();
                    transaction.Dispose();
                }

                //Throw exception
                throw;
            }
            finally
            {
                if (transaction != null)
                {
                    transaction.Dispose();
                }
            }
like image 276
LCJ Avatar asked Dec 08 '22 18:12

LCJ


2 Answers

How can we check whether the SqlTransaction is already disposed before calling Dispose()?

You don't have to. Calling dispose twice won't cause you any problem.

Dispose - MSDN

If an object's Dispose method is called more than once, the object must ignore all calls after the first one. The object must not throw an exception if its Dispose method is called multiple times. Instance methods other than Dispose can throw an ObjectDisposedException when resources are already disposed.

But if you want to only call Dispose once then you can either use a boolean flag to set when the transaction is disposed or you can set it to null. Or remove the call to dispose in catch block since finally block will always be called.

Since SqlTransaction implements IDisposable, its better if you use it with using block. Something like:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();

    using (SqlTransaction transaction = connection.BeginTransaction())
    {
        try
        {
            sessionID = GetSessionIDForAssociate(connection, empID, transaction);
            //Other code

            //Commit
            transaction.Commit();
        }
        catch
        {
            //Rollback
            if (transaction != null)
            {
                transaction.Rollback();
            }

            //Throw exception
            throw;
        }
    }
}

Since using block acts like try/finally block, and it will ensure the disposal of the transaction upon its completion (even if the exception occurs). So you don't have to manually call Dispose.

like image 149
Habib Avatar answered Dec 11 '22 09:12

Habib


Add transaction=null after you call dispose and then your existing tests will work.

like image 36
Bob Vale Avatar answered Dec 11 '22 09:12

Bob Vale