4

我有以下使用 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

注意:我已经知道它TransactionScopeSqlTransaction. 但我试图了解 SqlTransaction 的处置。

代码

 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

4 回答 4

8

我们如何在调用 Dispose() 之前检查 SqlTransaction 是否已经被释放?

你不必。调用 dispose 两次不会给您带来任何问题。

处置 - MSDN

如果多次调用对象的 Dispose 方法,则对象必须忽略第一次调用之后的所有调用。如果多次调用其 Dispose 方法,则该对象不得引发异常。当资源已被释放时,除 Dispose 之外的实例方法可能会引发 ObjectDisposedException。

但是,如果您只想调用一次 Dispose,那么您可以使用布尔标志来设置事务何时被处理,或者您可以将其设置为 null。或者删除对 dispose 的调用,catch因为finallyblock 总是会被调用。

由于 SqlTransaction 实现了IDisposable因此如果将它与 using block 一起使用会更好。就像是:

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.

于 2013-01-21T12:42:35.227 回答
2

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

于 2013-01-21T12:38:33.373 回答
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();
        }
    }
于 2013-01-21T12:40:36.087 回答
2

.Dispose()从 catch 块中删除调用。finally 总是被执行,所以这样你会尝试两次来处理事务。

它没有回答“我怎么知道它是否已经被处理”,但可能会解决您的问题。

于 2013-01-21T12:41:51.363 回答