C# Transaction 事務處理 -環境事務


 一、TransactionScope 環境事務

 1    static async Task TransactionScopeAsync()
 2         {
 3             using (var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
 4             {
 5                 Transaction.Current.TransactionCompleted += OnTransactionCompleted;
 6 
 7                 Utilities.DisplayTransactionInformation("Ambient TX created",
 8                       Transaction.Current.TransactionInformation);
 9                 
10                 var s1 = new Student
11                 {
12                     FirstName = "Angela",
13                     LastName = "Nagel",
14                     Company = "Kantine M101"
15                 };
16                 var db = new StudentData();
17                 await db.AddStudentAsync(s1);
18 
19                 if (!Utilities.AbortTx())
20                     scope.Complete();
21                 else
22                     Console.WriteLine("transaction will be aborted");
23 
24             } // scope.Dispose()
25 
26         }

 二、嵌套事務

 1  static void NestedScopes()
 2         {
 3             using (var scope = new TransactionScope())
 4             {
 5                 Transaction.Current.TransactionCompleted += OnTransactionCompleted;
 6 
 7                 Utilities.DisplayTransactionInformation("Ambient TX created",
 8                       Transaction.Current.TransactionInformation);
 9 
10                 using (var scope2 =
11                       new TransactionScope(TransactionScopeOption.RequiresNew))
12                 {
13                     Transaction.Current.TransactionCompleted += OnTransactionCompleted;
14 
15                     Utilities.DisplayTransactionInformation(
16                            "Inner Transaction Scope",
17                            Transaction.Current.TransactionInformation);
18 
19                     scope2.Complete();
20                 }
21                 scope.Complete();
22             }
23 
24         }

 

事務完成代碼

1   static void OnTransactionCompleted(object sender, TransactionEventArgs e)
2         {
3             Utilities.DisplayTransactionInformation("TX completed",
4                   e.Transaction.TransactionInformation);
5         }

 

 

你可能不知道這一點,在 .NET Framework 4.5.0  版本中包含有一個關於 System.Transactions.TransactionScope 在與 async/await 一起工作時會產生的一個嚴重的 bug 。由於這個錯誤,TransactionScope 不能在異步代碼中正常操作,它可能更改事務的線程上下文,導致在處理事務作用域時拋出異常。

這是一個很大的問題,因為它使得涉及事務的異步代碼極易出錯。

好消息是,在 .NET Framework 4.5.1 版本中,微軟發布了這個 "異步連接" 錯誤的修復程序。作為開發者的我們需要明確的做到以下兩點:

  • 如果說你在 TransactionScope 代碼中使用 async/await,你需要將框架升級到 .NET 4.5.1 或以上版本。
  • 在有包裝異步代碼的 TransactionScope 的構造函數中指定 TransactionScopeAsyncFlowOption.Enabled .

TransactionScopeAsyncFlowOption

在 .NET 4.5.1中,TransactionScope 有一個名為 TransactionScopeAsyncFlowOption 的新枚舉,可以在構造函數中提供。 您必須通過指定,明確地選擇跨線程連續的事務流,如下:

1 using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
2 {
3     await SomeMethodInTheCallStackAsync()
4         .ConfigureAwait(false);
5 
6     tx.Complete();
7 }

你可能很好奇,默認的 TransactionScopeAsyncFlowOption 是 Suppress(阻止的),因為微軟想避免破壞 .NET 4.5.0 版本中代碼庫中行為。

最后

使用 TransactionScope 結合 async / await 時,你應該更新所有使用 TransactionScope 的代碼路徑以啟用 TransactionScopeAsyncFlowOption.Enabled 。 這樣才能使事務能夠正確地流入異步代碼,防止在TransactionScope下使用時業務邏輯不正常。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM