How to check state before disposing SqlTransaction

我的未来我决定 提交于 2019-12-23 12:20:16

问题


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();
                }
            }

回答1:


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.




回答2:


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




回答3:


Why do you want to check to see whether it's been disposed already? You can avoid calling Dispose twice by simply omitting the call from your catch block:

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)
        {
            // No need to dispose here - finally is always called
            transaction.Rollback();
        }

        //Throw exception
        throw;
    }
    finally
    {
        if (transaction != null)
        {
            // Always called, so no need to dispose elsewhere.
            transaction.Dispose();
        }
    }



回答4:


Remove the .Dispose() call from catch block. Finally is ALWAYS executed, so this way you are trying two times to dispose transaction.

It does not answer "how can I know if it was already disposed" but probably solve your problem.



来源:https://stackoverflow.com/questions/14438736/how-to-check-state-before-disposing-sqltransaction

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!