Dot-Net

SqlTransaction 是否需要呼叫 Dispose?

  • May 25, 2021

我需要在 SqlTransaction 的 finally 塊中呼叫 dispose 嗎?假裝開發人員沒有在任何地方使用 USING,然後嘗試/擷取。

SqlTransaction sqlTrans = con.BeginTransaction();

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

          sqlTrans.Rollback();
       }

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

我是否需要使用try-finallyusing-statement 來處理SqlTransaction?

擁有它並沒有什麼壞處。對於每個實現IDisposable的類都是如此,否則它不會實現這個介面。

但通常垃圾收集器處理未引用的對象(這並不意味著 GC 呼叫 dispose,這不是真的),因此您只需要它來處理非託管資源。但是因為我也不想呼叫dispose所有其他變數或到處使用using 語句,所以研究類方法的實際實現總是值得的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這一點也可能是一個好主意:

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也會在創建 Transaction 時保持 Connection 處於活動狀態。它也不包含對事務的引用,因為它只返回它。因此,即使連接已經被釋放,它也可能不會被釋放。處置交易的另一個論據。

您可能還會TransactionScope查看BeginTransaction. 查看此問題以獲取更多資訊。

引用自:https://stackoverflow.com/questions/9525307