您好,登錄后才能下訂單哦!
目錄
一、事務的定義
二、事務管理器
三、在ADO.NET中實現事務
四、隱式事務 TransactionScope
五、在WCF中實現事務
六、嵌套式事務
七、異步事務
六、嵌套式事務
嵌套式事務經常會出現在項目中,但往往容易被大家忽略,下面介紹一下 嵌套式事務的用法:
1 using (TransactionScope scope1 = new TransactionScope()) 2 { 3 .............. 4 using (TransactionScope scope2=new TransactionScope(TransactionScopeOption.RequiresNew)) 5 { 6 .............. 7 scope2.Complete(); //只完成嵌套式的內部事務,但事務并未正式提交
8 } 9 scope1.Complete(); //代表完成所有事務,事務正式提交
10 }
一 般項目中,大家都只會把事務用在DAL層,用于管理數據的CRUD,但其實在一些操作中,某些數據的操作必須具有一致性。比如在訂單管理中,當插入一條 OrderItem時,Order表內的總體價格,商品數量等也會隨之改變。很多人把兩個表的操作合成一個方法,放在OrderDAL中完成。但其實這樣 做違返設計的原則,因為計算Order的總體價格時可能會包含商品優惠、客戶等級、客戶積分等等業務邏輯,而在DAL層不應該包含任何的業務邏輯存在的, 所以這樣操作應該放在業務層完成。這時候,業務層的方法內就需要同時調用OrderItemDAL的AddOrderItem(OrderItem) 方法和OrderDAL的UpdateOrder(Order)方法,為了保證數據的一致性更新,就需要使用嵌套式事務。但這往往容易被開發人員所忽略, 當Order表的更新成功而OrderItem表的插入失敗時,系統不能保證數據的同步回滾,那就會造成數據的邏輯性錯誤。
下面的例子就是為了保證數據一致性更新而使用的嵌套式事務,在使用嵌套式事務的時候要應該注意及其把對象釋放,避免做成死鎖。
1 namespace DAL 2 { 3 public class OrderDAL 4 { 5 public void UpdateOrder(Order order) 6 { 7 using (TransactionScope scope = new TransactionScope()) 8 { 9 ...... 10 scope.Complete(); 11 } 12 } 13 } 14 15 public class OrderItemDAL 16 { 17 public void AddOrderItem(OrderItem orderItem) 18 { 19 using (TransactionScope scope = new TransactionScope()) 20 { 21 ...... 22 scope.Complete(); 23 } 24 } 25 } 26 } 27 28 namespace BLL 29 { 30 public class OrderManager 31 { 32 public void AddOrderItem(OrderItem item) 33 { 34 using (TransactionScope scope = new TransactionScope()) 35 { 36 OrderItemDAL orderItemDAL=new OrderItemDAL(); 37 orderItemDAL.AddOrderItem(item); 38 OrderDAL orderDAL=new OrderDAL(); 39 ........ 40 orderDAL.UpdateOrder(order); 41 scope.Complete(); 42 } 43 } 44 } 45 }
回到目錄
七、異步事務
記得在第二節的時候曾經提起過事務類Transaction的方法中包含方法
public DependentTransaction DependentClone(DependentCloneOption)
此方法作用是克隆當前的事務,它在多線程調用同一事務的情況下使用經常使用。其中DependentCloneOption包含有兩個選項:
一為BlockCommitUntilComplete,這表示在依賴事務未完成前,事務將處于阻塞狀態,只有在所有依賴事務完成后,事務才能執行提交;
二為RollbackInNotComplete,這表示依賴事務必須在事務完成前調用Complete(),否則事務會被視為失敗。
在 普通情況下,事務都會通過Transaction.Current 來獲取,但此方法只能獲取當前線程下的事務對象,在異步方法當中,這只會返回一個空值 null 。此時就需要使用DependentClone 方法獲取依賴事務對象 DependentTransaction ,再把此對象作為參數傳遞到回調函數中。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Method(); 6 Console.ReadKey(); 7 } 8 9 static void Method() 10 { 11 using (TransactionScope scope = new TransactionScope()) 12 { 13 ShowMessage("Main Thread"); 14 15 //獲取一個依賴事務,把依賴事務作為回調參數傳到回調函數中
16 DependentTransaction dependentTransaction= 17 Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete); 18 ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncThread), dependentTransaction); 19 ........ 20 scope.Complete(); //完成主線程事務,在依賴事務完成前,事務提交將處于阻塞狀態 21 } 22 } 23 24 static void AsyncThread(object transaction) 25 { 26 //獲取依賴事務,利用TransactionScope(Transaction)構造函數生成隱式事務
27 DependentTransaction dependentTransaction = (DependentTransaction)transaction; 28 using (TransactionScope scope = new TransactionScope(dependentTransaction)) 29 { 30 ShowMessage("AsyncThread"); 31 .......... 32 scope.Complete(); //完成異步事務
33 } 34 //完成依賴事務
35 dependentTransaction.Complete(); 36 } 37 38 static void ShowMessage(string data) 39 { 40 if (Transaction.Current != null) 41 { 42 Transaction transaction = Transaction.Current; 43 string info = string.Format("{0}:{1}\nTransaction:\n DistributedIndentifier:{2} \n LocalIndentifier:{3}\n", 44 data,Thread.CurrentThread.ManagedThreadId.ToString(), 45 transaction.TransactionInformation.DistributedIdentifier, 46 transaction.TransactionInformation.LocalIdentifier); 47 Console.WriteLine(info); 48 } 49 } 50 }
首 先在主線程中利用 Transaction.DependentClone(DependentCloneOption.BlockCommitUntilComplete) 方法生成一個依賴事務,注意方法使用了BlockCommitUntilComplete的方式生成,即事務將在所有依賴事務使用Complete()后 才能執行提交。
然后利用ThreadPool.QueueUserWorkItem(WaitCallback,Object)方法把依賴事務作為回調參數傳遞到回調函數中。
最后在回調函數中使用TransactionScope(transaction)構造函數生成對象,這代表把參數transaction作為當前的環境事務對象。觀察下面的運行結果,兩個線程中的事務都是同一個事務。
結束語
事務是在多個層次都會使用到的,但很多項目當中往往會忽略了這一點而只在數據層使用,在大型的系統當中這樣可能會影響到系統的一致性。特別是在分布式系統當中,操作往往同時存在于多個不同的系統當中,事務的處理更顯示出其重要性。
希望本篇文章對相關的開發人員有所幫助。對JAVA與.NET開發有興趣的朋友歡迎加入QQ群:162338858
回到目錄
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。