SqlTransaction 是否需要调用 Dispose?

Does SqlTransaction need to have Dispose called?(SqlTransaction 是否需要调用 Dispose?)
本文介绍了SqlTransaction 是否需要调用 Dispose?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我需要在 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();
        }

推荐答案

我是否需要使用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.

您还可以查看TransactionScope 类 比 BeginTransaction 更安全.查看这个问题了解更多信息.

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.

这篇关于SqlTransaction 是否需要调用 Dispose?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

How to register System.DirectoryServices for use in SQL CLR User Functions?(如何注册 System.DirectoryServices 以在 SQL CLR 用户函数中使用?)
Query From LDAP for User Groups(从 LDAP 查询用户组)
How can I get DOMAINUSER from an AD DirectoryEntry?(如何从 AD DirectoryEntry 获取 DOMAINUSER?)
Get a list of members of a WinNT group(获取 WinNT 组的成员列表)
Get UPN or email for logged in user in a .NET web application(在 .NET Web 应用程序中获取登录用户的 UPN 或电子邮件)
Active Directory Group Membership Checking in .Net 4.5(.Net 4.5 中的 Active Directory 组成员身份检查)