.net SqlTransaction是否需要调用Dispose?
我是否需要在SqlTransaction的finally块中调用dispose?假装开发人员没有在任何地方使用USING,然后尝试/捕获.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 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,theDispose()
方法应该检查它是否已被释放,如果已被释放,则什么也不做。@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;
}