.net SqlTransaction是否需要调用Dispose?

.net SqlTransaction是否需要调用Dispose?,.net,transactions,dispose,sqltransaction,.net,Transactions,Dispose,Sqltransaction,我是否需要在SqlTransaction的finally块中调用dispose?假装开发人员没有在任何地方使用USING,然后尝试/捕获 SqlTransaction sqlTrans = con.BeginTransaction(); try { //Do Work sqlTrans.Commit() } catch (Exception ex) { sqlTrans.Rollback(); } finally

我是否需要在SqlTransaction的finally块中调用dispose?假装开发人员没有在任何地方使用USING,然后尝试/捕获

SqlTransaction sqlTrans = con.BeginTransaction();

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

           sqlTrans.Rollback();
        }

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

在一般情况下,您构造或获取并拥有的每个
IDisposable
对象都必须进行处置

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

根据:

释放DbTransaction使用的非托管资源,并可以选择释放托管资源

(我的重点)


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

我认为您可以关闭连接。我检查了BCL的代码——好像连接负责它的事务——不需要显式关闭它

我是否需要使用
try finally
using
-语句来处理
SqlTransaction

拥有它并没有坏处。这对于实现的每个类都是正确的,否则它不会实现这个接口

但通常情况下,它处理的是未引用的对象(这并不意味着GC调用dispose,dispose),因此您只需要它来处理。但是,因为我也不想对每个其他变量调用
dispose
,也不想使用everywhere,所以始终值得研究类“
dispose
方法的实际实现

:

不了解这里发生的一切(或任何事情),我可以说这不仅仅是一个简单的
base.Dispose(disposing)
。因此,确保处理SqlTransaction可能是一个好主意

但是由于
SqlConnection.BeginTransaction
创建了事务,因此也可以这样做:

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;
}
公共SqlTransaction BeginTransaction(IsolationLevel iso,字符串transactionName) { SqlStatistics=null; 字符串a=ADP.IsEmpty(transactionName)?“无”:transactionName; IntPtr IntPtr; Bid.ScopeEnter(out intPtr,“%d#,iso=%d{ds.IsolationLevel},transactionName='%ls'\n”,this.ObjectID,(int)iso,a); SqlTransaction结果; 尝试 { statistics=SqlStatistics.StartTimer(this.statistics); SqlTransaction SqlTransaction=this.GetOpenConnection().BeginSqlTransaction(iso,transactionName); GC.KeepAlive(本); 结果=sqlTransaction; } 最后 { 投标范围(参考intPtr); SqlStatistics.StopTimer(统计); } 返回结果; } 如你所见。在创建事务时,还将保持连接处于活动状态。它也不保存对事务的引用,因为它只返回它。因此,即使连接已被释放,也可能不会被释放。处理事务的另一个参数


您还可以查看比
BeginTransaction
更安全的。查看以获取更多信息。

拥有它没有坏处。如果您没有在
sqlTrans
周围使用
using
,那么显式调用
Dispose()
当然没有坏处。@Cory在调用sqlTrans.Dispose()之前需要检查sqlTrans是否已经被释放吗?@Lijo:No,the
Dispose()
方法应该检查它是否已被释放,如果已被释放,则什么也不做。@Cory在下面的问题中回答说相反,您可能还需要查看BeginSqlTransaction()和Connection.Dispose()代码。SqlTransaction似乎是在Connection.Dispose()中清除的InternalTransaction周围的一个wrpapper。我不同意注释
,这对于实现IDisposable的每个类都是如此。TableCell控件和其他HTML控件怎么样。建议不要对它们使用“using”。@Lijo:重点是,这太笼统了。如果需要处置一些非托管资源(如数据库连接),只需重写实现或使用
using
-语句。控件实现
IDposable
,因为该控件(例如
UserControl
)可能包含非托管资源,并且将在生命周期结束时进行处置(递归页面进入所有子控件)。一旦
SqlConnection
被处理掉,
SqlTransaction
就不会被处理掉吗?@zig:读我的答案:“在创建事务时,GC还将使连接保持活动状态。它也不保存对事务的引用,因为它只返回它。因此,即使连接已被释放,也可能不会被释放。处理事务的另一个理由是“更多的细节,如代码摘录,将有助于增强信心。
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;
}