如何在处理SqlTransaction之前检查状态

时间:2013-01-21 12:35:28

标签: c# .net ado.net

我有以下使用SqlTransaction的代码。我已经在catch中调用dispose并最终阻止了..但是在调用Dispose()之前我还没有检查它是否已经处理掉了。在调用Dispose()之前,我们如何检查SqlTransaction是否已被释放?

我已提到MSDN:SqlTransaction.Dispose Method。但这并不包括我的问题。

同时提到http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqltransaction.dispose(v=vs.100).aspx

注意:我已经知道TransactionScope优于SqlTransaction。但我试图了解SqlTransaction的配置。

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

4 个答案:

答案 0 :(得分:8)

  

我们如何检查之前是否已经处理过SqlTransaction   调用Dispose()?

你不必。两次调用处置不会对您造成任何问题。

Dispose - MSDN

  

如果对象的Dispose方法被多次调用,则该对象   必须忽略第一个之后的所有呼叫。该对象不得抛出   如果多次调用Dispose方法,则会出现异常。例   Dispose以外的方法可以在何时抛出ObjectDisposedException   资源已经处理完毕。

但是如果你只想调用Dispose一次,那么你可以使用布尔标志来设置事务处理时间,也可以将其设置为null。或者在catch块中删除要处置的调用,因为始终会调用finally块。

由于SqlTransaction实现IDisposable如果你使用块则更好。类似的东西:

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

由于使用块行为类似于try/finally块,因此它将确保在事务完成时处理事务(即使发生异常)。因此,您无需手动拨打Dispose

答案 1 :(得分:2)

在调用dispose之后添加transaction=null,然后您的现有测试将起作用。

答案 2 :(得分:2)

为什么要查看是否已经处理过?您可以通过简单地省略Dispose块中的来电来避免致电catch两次:

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

答案 3 :(得分:2)

从catch块中删除.Dispose()调用。最后总是被执行,所以这样你就会尝试两次处理交易。

它没有回答“我怎么知道它是否已被处置”,但可能解决了你的问题。