閱讀1004 返回首頁    go 阿裏雲 go 技術社區[雲棲]


WCF技術剖析之三十一:WCF事務編程[上篇]

WCF事務編程其實很簡單,可以用三句話進行概括:通過服務契約決定事物流轉(Transaction Flow)的策略通過綁定實施事務的流轉通過服務行為控製事務的相關行為。本篇文章著重介紹如果通過TransactionFlowAttribute特性定義事務流轉策略。 

契約時是一種雙邊協定,是雙方就某個關注點達成的一種共識。對於分布式事務的實現來講,首先需要解決的是事務流轉的問題,即事務將客戶端的事務流向服務端。要解決事務流轉的問題,需要在事務的發送方和接收方就流轉問題達成共識,即雙方采用相匹配的事務發送和接收策略。毫無疑問,這樣的開關需要定義在服務契約之上,同時事務是基於服務操作的,所以事務流轉策略最終應用到操作契約上麵。

WCF通過TransactionFlowAttribute特性將相應的事務流轉策略關聯到某個服務之上,具體來講,我們在定義服務契約的時候,直接將TransactionFlowAttribute特性應用到相應的操作契約上即可。我們先來看看TransactionFlowAttribute的定義,從下麵的代碼我們可以看到,TransactionFlowAttribute並僅僅是一個簡單的自定義特性,它更是一個操作行為。至於該操作行為對事務流轉行為作了怎樣的控製,會在後續的文章詳細講述。

   1: [AttributeUsage(AttributeTargets.Method)]
   2: public sealed class TransactionFlowAttribute : Attribute, IOperationBehavior
   3: {   
   4:     //其他成員
   5:     public TransactionFlowAttribute(TransactionFlowOption transactions);
   6:     public TransactionFlowOption Transactions { get; }
   7: }

當我們將TransactionFlowAttribute特性應用到操作契約的時候,具體事務流轉策略通過TransactionFlowOption枚舉指定,TransactionFlowOption定義如下。

   1: public enum TransactionFlowOption
   2: {
   3:     NotAllowed,
   4:     Allowed,
   5:     Mandatory
   6: }

TransactionFlowOption一共定義了三選項:NotAllowed、Allowed和Mandatory,它們的分別代表的事務流轉策略如下:

  • NotAllowed客戶端的事務不允許被流轉到服務端;服務端也不會試圖去接收流入的事務,這是默認選項;
  • Allowed如果客戶端事務存在,則被流轉到服務端;服務端會試圖去接收流入的事務;
  • Mandatory客戶端必須在一個事務中進行服務調用,相應的事務並會被流轉到服務端;服務端接收到的消息中必須包含被序列化的事務。

在下麵定義的IBankingService服務契約中,我們將TransactionFlowAttribute特性應用到了用於進行轉帳操作的Transfer方法之上,並指定事務流轉選項為Mandatory。

   1: [ServiceContract(Namespace = "https://www.artech.com/")]
   2: public interface IBankingService
   3: {
   4:     [OperationContract]
   5:     [TransactionFlow(TransactionFlowOption.Mandatory)]
   6:     void Transfer(string accountFrom, string accountTo, double amount);
   7: }

對於Mandatory選項,如果客戶端在進行服務調用的時候並不存在事務,或者說服務端並沒有接收到任何流入的事務(當客戶端和服務端采用的契約定義了不匹配的事務流轉策略時會出現這種情況下,比如客戶端采用NotAllowed選項,客戶端則采用Mandatory,那麼服務端永遠也接收不到流入的事務),都會拋出如圖1所示的ProtocolException異常。

image 圖1 在選用Mandatory選項下客戶端不存在事務導致的異常

事務從客戶端流轉到服務端後,服務端可以中止事務,並將結果返回到客戶端。從這個意義上講,事務流轉建立在請求/回複消息交換模式(MEP)之上,所以,在一個單向(One-Way)操作契約上,不允許應用TransactionFlowAttribute並指定Allowed或者Mandatory選項。比如下麵的服務契約定義是不合法的:

   1: [ServiceContract(Namespace = "https://www.artech.com/")]
   2: public interface IBankingService
   3: {
   4:     [OperationContract(IsOneWay = true)]
   5:     [TransactionFlow(TransactionFlowOption.Mandatory)]
   6:     void Transfer(string accountFrom, string accountTo, double amount);
   7: }

如果某個服務實現了這樣的服務契約,在進行服務寄宿的時候,會拋出如圖2所示的InvalidOperationException異常(如果仔細的話還會看到VS一個漢化的問題:“單項”應該是“單向”,嗬嗬!!)。

image

圖2  在單向操作上應用TransactionFlowAttribute特性導致的異常



作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-27 16:04:40

  上一篇:go  談談分布式事務之四: 兩種事務處理協議OleTx與WS-AT
  下一篇:go  WCF技術剖析之三十一: WCF事務編程[中篇]