問題描述
我需要在 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-finally
或using
-statement 來處理SqlTransaction
?
Do I need to use
try-finally
or theusing
-statement to dispose theSqlTransaction
?
擁有它并沒有什么壞處.對于實現 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?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!