您好,登錄后才能下訂單哦!
目錄
一、事務(wù)的定義
二、事務(wù)管理器
三、在ADO.NET中實(shí)現(xiàn)事務(wù)
四、隱式事務(wù) TransactionScope
五、在WCF中實(shí)現(xiàn)事務(wù)
六、嵌套式事務(wù)
七、異步事務(wù)
六、嵌套式事務(wù)
嵌套式事務(wù)經(jīng)常會(huì)出現(xiàn)在項(xiàng)目中,但往往容易被大家忽略,下面介紹一下 嵌套式事務(wù)的用法:
1 using (TransactionScope scope1 = new TransactionScope()) 2 { 3 .............. 4 using (TransactionScope scope2=new TransactionScope(TransactionScopeOption.RequiresNew)) 5 { 6 .............. 7 scope2.Complete(); //只完成嵌套式的內(nèi)部事務(wù),但事務(wù)并未正式提交
8 } 9 scope1.Complete(); //代表完成所有事務(wù),事務(wù)正式提交
10 }
一 般項(xiàng)目中,大家都只會(huì)把事務(wù)用在DAL層,用于管理數(shù)據(jù)的CRUD,但其實(shí)在一些操作中,某些數(shù)據(jù)的操作必須具有一致性。比如在訂單管理中,當(dāng)插入一條 OrderItem時(shí),Order表內(nèi)的總體價(jià)格,商品數(shù)量等也會(huì)隨之改變。很多人把兩個(gè)表的操作合成一個(gè)方法,放在OrderDAL中完成。但其實(shí)這樣 做違返設(shè)計(jì)的原則,因?yàn)橛?jì)算Order的總體價(jià)格時(shí)可能會(huì)包含商品優(yōu)惠、客戶(hù)等級(jí)、客戶(hù)積分等等業(yè)務(wù)邏輯,而在DAL層不應(yīng)該包含任何的業(yè)務(wù)邏輯存在的, 所以這樣操作應(yīng)該放在業(yè)務(wù)層完成。這時(shí)候,業(yè)務(wù)層的方法內(nèi)就需要同時(shí)調(diào)用OrderItemDAL的AddOrderItem(OrderItem) 方法和OrderDAL的UpdateOrder(Order)方法,為了保證數(shù)據(jù)的一致性更新,就需要使用嵌套式事務(wù)。但這往往容易被開(kāi)發(fā)人員所忽略, 當(dāng)Order表的更新成功而OrderItem表的插入失敗時(shí),系統(tǒng)不能保證數(shù)據(jù)的同步回滾,那就會(huì)造成數(shù)據(jù)的邏輯性錯(cuò)誤。
下面的例子就是為了保證數(shù)據(jù)一致性更新而使用的嵌套式事務(wù),在使用嵌套式事務(wù)的時(shí)候要應(yīng)該注意及其把對(duì)象釋放,避免做成死鎖。
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 }
回到目錄
七、異步事務(wù)
記得在第二節(jié)的時(shí)候曾經(jīng)提起過(guò)事務(wù)類(lèi)Transaction的方法中包含方法
public DependentTransaction DependentClone(DependentCloneOption)
此方法作用是克隆當(dāng)前的事務(wù),它在多線(xiàn)程調(diào)用同一事務(wù)的情況下使用經(jīng)常使用。其中DependentCloneOption包含有兩個(gè)選項(xiàng):
一為BlockCommitUntilComplete,這表示在依賴(lài)事務(wù)未完成前,事務(wù)將處于阻塞狀態(tài),只有在所有依賴(lài)事務(wù)完成后,事務(wù)才能執(zhí)行提交;
二為RollbackInNotComplete,這表示依賴(lài)事務(wù)必須在事務(wù)完成前調(diào)用Complete(),否則事務(wù)會(huì)被視為失敗。
在 普通情況下,事務(wù)都會(huì)通過(guò)Transaction.Current 來(lái)獲取,但此方法只能獲取當(dāng)前線(xiàn)程下的事務(wù)對(duì)象,在異步方法當(dāng)中,這只會(huì)返回一個(gè)空值 null 。此時(shí)就需要使用DependentClone 方法獲取依賴(lài)事務(wù)對(duì)象 DependentTransaction ,再把此對(duì)象作為參數(shù)傳遞到回調(diào)函數(shù)中。
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 //獲取一個(gè)依賴(lài)事務(wù),把依賴(lài)事務(wù)作為回調(diào)參數(shù)傳到回調(diào)函數(shù)中
16 DependentTransaction dependentTransaction= 17 Transaction.Current.DependentClone(DependentCloneOption.BlockCommitUntilComplete); 18 ThreadPool.QueueUserWorkItem(new WaitCallback(AsyncThread), dependentTransaction); 19 ........ 20 scope.Complete(); //完成主線(xiàn)程事務(wù),在依賴(lài)事務(wù)完成前,事務(wù)提交將處于阻塞狀態(tài) 21 } 22 } 23 24 static void AsyncThread(object transaction) 25 { 26 //獲取依賴(lài)事務(wù),利用TransactionScope(Transaction)構(gòu)造函數(shù)生成隱式事務(wù)
27 DependentTransaction dependentTransaction = (DependentTransaction)transaction; 28 using (TransactionScope scope = new TransactionScope(dependentTransaction)) 29 { 30 ShowMessage("AsyncThread"); 31 .......... 32 scope.Complete(); //完成異步事務(wù)
33 } 34 //完成依賴(lài)事務(wù)
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 }
首 先在主線(xiàn)程中利用 Transaction.DependentClone(DependentCloneOption.BlockCommitUntilComplete) 方法生成一個(gè)依賴(lài)事務(wù),注意方法使用了BlockCommitUntilComplete的方式生成,即事務(wù)將在所有依賴(lài)事務(wù)使用Complete()后 才能執(zhí)行提交。
然后利用ThreadPool.QueueUserWorkItem(WaitCallback,Object)方法把依賴(lài)事務(wù)作為回調(diào)參數(shù)傳遞到回調(diào)函數(shù)中。
最后在回調(diào)函數(shù)中使用TransactionScope(transaction)構(gòu)造函數(shù)生成對(duì)象,這代表把參數(shù)transaction作為當(dāng)前的環(huán)境事務(wù)對(duì)象。觀察下面的運(yùn)行結(jié)果,兩個(gè)線(xiàn)程中的事務(wù)都是同一個(gè)事務(wù)。
結(jié)束語(yǔ)
事務(wù)是在多個(gè)層次都會(huì)使用到的,但很多項(xiàng)目當(dāng)中往往會(huì)忽略了這一點(diǎn)而只在數(shù)據(jù)層使用,在大型的系統(tǒng)當(dāng)中這樣可能會(huì)影響到系統(tǒng)的一致性。特別是在分布式系統(tǒng)當(dāng)中,操作往往同時(shí)存在于多個(gè)不同的系統(tǒng)當(dāng)中,事務(wù)的處理更顯示出其重要性。
希望本篇文章對(duì)相關(guān)的開(kāi)發(fā)人員有所幫助。對(duì)JAVA與.NET開(kāi)發(fā)有興趣的朋友歡迎加入QQ群:162338858
回到目錄
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。