首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SqlTransaction需要调用Dispose吗?

SqlTransaction需要调用Dispose吗?
EN

Stack Overflow用户
提问于 2012-03-02 06:37:55
回答 3查看 14.7K关注 0票数 9

我需要在SqlTransaction的finally块中调用dispose吗?假装开发人员没有使用USING anywhere,只需要try/catch即可。

代码语言:javascript
复制
SqlTransaction sqlTrans = con.BeginTransaction();

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

           sqlTrans.Rollback();
        }

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

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-02 07:18:24

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

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

但通常情况下,garbage collector会处理未引用的对象(这并不意味着GC会调用dispose,后者是isn't true),所以只有unmanaged resources才需要它。但是,因为我也不想在每个其他变量上都调用dispose,或者在任何地方都使用using-statement,所以研究类的Dispose方法的实际实现总是值得的。

SqlTransaction.Dispose

代码语言:javascript
复制
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被释放可能是一个好主意。

但是因为SqlConnection.BeginTransaction创建了事务,所以reflect也是一个好主意:

代码语言:javascript
复制
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'\n", 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还将使连接保持活动状态。它也不持有对事务的引用,因为它只返回事务。因此,即使连接已经被释放,它也可能不会被释放。另一个处理事务的参数。

你也可以看看比BeginTransaction更安全的TransactionScope class。有关更多信息,请查看this question

票数 19
EN

Stack Overflow用户

发布于 2012-03-02 07:12:23

在一般情况下,您构造或获取并拥有的每个IDisposable对象都必须被清除。

在特定情况下,有一些例外,但SqlTransaction不是其中之一。

根据the documentation of SqlTransaction.Dispose

发布DbTransaction使用的非托管资源,并有选择地释放托管资源。

(我的重点)

由于文档没有说明在您发出提交或回滚时释放这些非托管资源,因此您将需要处理此对象。

票数 8
EN

Stack Overflow用户

发布于 2012-03-02 07:16:43

我认为你可以关闭连接。我检查了BCL的代码--看起来连接负责它的事务--不需要显式地关闭它。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9525307

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档