我需要在SqlTransaction的finally块中调用dispose吗?假装开发人员没有使用USING anywhere,只需要try/catch即可。
SqlTransaction sqlTrans = con.BeginTransaction();
try
{
//Do Work
sqlTrans.Commit()
}
catch (Exception ex)
{
sqlTrans.Rollback();
}
finally
{
sqlTrans.Dispose();
con.Dispose();
}发布于 2012-03-02 07:18:24
我是否需要使用
try-finally或using-statement来处置SqlTransaction?
拥有它也没什么坏处。对于实现IDisposable的每个类来说都是如此,否则它就不会实现这个接口。
但通常情况下,garbage collector会处理未引用的对象(这并不意味着GC会调用dispose,后者是isn't true),所以只有unmanaged resources才需要它。但是,因为我也不想在每个其他变量上都调用dispose,或者在任何地方都使用using-statement,所以研究类的Dispose方法的实际实现总是值得的。
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被释放可能是一个好主意。
但是因为SqlConnection.BeginTransaction创建了事务,所以reflect也是一个好主意:
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。
发布于 2012-03-02 07:12:23
在一般情况下,您构造或获取并拥有的每个IDisposable对象都必须被清除。
在特定情况下,有一些例外,但SqlTransaction不是其中之一。
根据the documentation of SqlTransaction.Dispose
发布DbTransaction使用的非托管资源,并有选择地释放托管资源。
(我的重点)
由于文档没有说明在您发出提交或回滚时释放这些非托管资源,因此您将需要处理此对象。
发布于 2012-03-02 07:16:43
我认为你可以关闭连接。我检查了BCL的代码--看起来连接负责它的事务--不需要显式地关闭它。
https://stackoverflow.com/questions/9525307
复制相似问题