2015-12-21 58 views
0
using (Transactions.TransactionScope tx = new Transactions.TransactionScope()) { 
    using (SqlConnection conn = new SqlConnection(CONNECTIONSTRING)) { 
     conn.Open(); 
     var cmd = new SqlCommand("Update Officer1s Set isLocked='Y' where a='b'", conn); //refer to an nonexsiting name on purpose. 
     var transaction = conn.BeginTransaction(); 
     cmd.Transaction = transaction; 
     try { 
      var a = cmd.ExecuteNonQuery(); 
     } catch (Exception ex) { 
      transaction.Rollback();//Invalid object name 'Officer1s'. 
     } 

     using (SqlConnection conn2 = new SqlConnection(CONNECTIONSTRING)) { 
      conn2.Open(); //throw exception 
     } 
    } 
} 

在我真正的應用程序中,入口方法被TransactionScope包圍。入口方法調用了很多方法,並且非常深入。如果在任何連接中,sql拋出任何SqlException異常(爲了演示,我故意指向一個非異常名稱)並回滾內部事務,然後我無法打開第二個連接,因爲會拋出異常「說明事務已中止」。在嵌套事務中打開第二個連接導致錯誤

爲什麼外部事務中止?這種用法是否受支持?

我使用SQL Server 2014

+0

sql-server中的嵌套事務是一個神話。 「外部」交易並不是什麼,而是增加交易計數的價值。回滾將回滾事務並將計數器重置爲0。 –

回答

0

你越來越能取決於多種因素,如是否使用的是交易池的特定行爲。然而,總的來說,這不是交易的工作方式。

連接非常昂貴,所以您希望打開一個連接並反覆使用它。事務存在於連接中,因此在另一個連接上使用相同的事務對象是無效的。

從樣本來看,代碼看起來並不像使用嵌套事務,而是「嵌套連接」,這不是正確的解決方法。發生的事情是:

  • 連接
    • 開始交易
      • DML語句
      • DML語句...
    • 提交/回滾
    • 開始交易
      • DML語句...
    • 提交/回滾
  • 釋放連接

如果你願意,你可以打開SQL Server的管理工作室兩個查詢會話。在第一個中,執行BEGIN TRAN,然後在表格中插入一行。現在,如果不執行COMMIT,請切換到其他會話並查詢表格。你不會看到你剛剛添加的行(除非你的隔離級別是髒讀;我希望不是)。這是交易的性質隔離

上述代碼應該發生的情況是,當異常被捕獲並且事務回滾時,事務對象完成。下一個邏輯工作單元以新的BeginTransaction()開始。

相關問題