• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

SqlTransaction 是否需要调用 Dispose?

用户头像
it1352
帮助2

问题说明

我需要在 SqlTransaction 的 finally 块中调用 dispose 吗?假设开发者没有在任何地方使用 USING,只是尝试/捕获.

Do I need to call dispose in the finally block for SqlTransaction? Pretend the developer didnt use USING anywhere, and just try/catch.

SqlTransaction sqlTrans = con.BeginTransaction();

try
{
     //Do Work
sqlTrans.Commit()
}
catch (Exception ex)
        {

           sqlTrans.Rollback();
        }

 finally
        {
            sqlTrans.Dispose();
            con.Dispose();
        }

正确答案

#1

我是否需要使用try-finallyusing-statement 来处理SqlTransaction?

Do I need to use try-finally or the using-statement to dispose the SqlTransaction?

拥有它并没有什么坏处.对于实现 IDisposable 的每个类都是如此,否则它会不实现这个接口.

It does not hurt to have it. This is true for every class implementing IDisposable, otherwise it would not implement this interface.

但通常垃圾收集器处理未引用的对象(这并不意味着 GC 调用了 dispose,这 不正确),因此您只需要非托管资源.但是因为我也不想在所有其他变量上调用 dispose 或使用 using-statement 无处不在,研究类的 Dispose 方法的实际实现总是值得的.

But normally the garbage collector deals with unreferenced objects(it doesn't mean that the GC calls dispose, which isn't true), so you need it only for unmanaged resources. But because i also don't want to call dispose on every other variable or use the using-statement everywhere, it it's always worth to look into the actual implementation of the class' Dispose method.

SqlTransaction.Dispose:

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        SNIHandle target = null;
        RuntimeHelpers.PrepareConstrainedRegions();
        try
        {
            target = SqlInternalConnection.GetBestEffortCleanupTarget(this._connection);
            if (!this.IsZombied && !this.IsYukonPartialZombie)
            {
                this._internalTransaction.Dispose();
            }
        }
        catch (OutOfMemoryException e)
        {
            this._connection.Abort(e);
            throw;
        }
        catch (StackOverflowException e2)
        {
            this._connection.Abort(e2);
            throw;
        }
        catch (ThreadAbortException e3)
        {
            this._connection.Abort(e3);
            SqlInternalConnection.BestEffortCleanup(target);
            throw;
        }
    }
    base.Dispose(disposing);
}
        

在不了解这里发生的所有(或任何事情)的情况下,我可以说这不仅仅是一个简单的 base.Dispose(disposing).因此,确保 SqlTransaction 被释放可能是一个好主意.

Without understanding all(or anything) what is happening here i can say that this is more than a simple base.Dispose(disposing). So it might be a good idea to ensure that a SqlTransaction gets disposed.

但是因为 SqlConnection.BeginTransaction 创建了事务,所以 反映这一点:

But because SqlConnection.BeginTransaction creates the transaction it could also be a good idea to reflect this also:

public SqlTransaction BeginTransaction(IsolationLevel iso, string transactionName)
{
    SqlStatistics statistics = null;
    string a = ADP.IsEmpty(transactionName) ? "None" : transactionName;
    IntPtr intPtr;
    Bid.ScopeEnter(out intPtr, "<sc.SqlConnection.BeginTransaction|API> %d#, iso=%d{ds.IsolationLevel}, transactionName='%ls'
", this.ObjectID, (int)iso, a);
    SqlTransaction result;
    try
    {
        statistics = SqlStatistics.StartTimer(this.Statistics);
        SqlTransaction sqlTransaction = this.GetOpenConnection().BeginSqlTransaction(iso, transactionName);
        GC.KeepAlive(this);
        result = sqlTransaction;
    }
    finally
    {
        Bid.ScopeLeave(ref intPtr);
        SqlStatistics.StopTimer(statistics);
    }
    return result;
}

如你所见.GC 还将在创建事务时保持连接处于活动状态.它也不持有对交易的引用,因为它只返回它.因此,即使连接已被处理,它也可能不会被处理.处理交易的另一个论据.

As you can see. The GC will also keep the Connection alive when a Transaction is created. It also doesn't hold a reference to the transaction since it only returns it. Hence it might not be disposed even when the connection is already disposed. Another argument to dispose the transaction.

您还可以查看TransactionScopeBeginTransaction 更安全.查看这个问题了解更多信息.

You might also have a look at the TransactionScope class which is more fail-safe than BeginTransaction. Have a look at this question for more informations.

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /reply/detail/tangibfge
系列文章
更多 icon
同类精品
更多 icon
继续加载