WCF - 事務



WCF中的事務是一組遵循某些屬性的操作,這些屬性統稱為ACID。在這裡,如果單個操作失敗,則整個系統會自動失敗。線上下訂單時,就會發生事務。以下示例有助於更簡單地理解事務過程。

示例

假設您從線上商店訂購了一臺液晶電視,並且您將使用信用卡支付款項。當您輸入必要的資料下單時,會同時發生兩個操作。

一個是從您的銀行賬戶中扣除指定金額,第二個是向供應商賬戶貸記相同金額。為了成功完成事務,這兩個操作都必須成功執行。

WCF事務屬性

WCF事務遵循的四個屬性如下:

  • 原子性 - 所有操作都必須在事務完成後作為一個不可分割的單個操作。

  • 一致性 - 無論操作集是什麼,系統始終處於一致狀態,即事務的結果始終符合預期。

  • 隔離性 - 系統的中間狀態在事務完成之前對外部世界的任何實體都是不可見的。

  • 永續性 - 無論發生任何型別的故障(硬體、電源中斷等),都會保持已提交狀態。

配置WCF事務時,需要考慮一些因素。這些是繫結和操作行為。

繫結 - 支援WCF中事務的繫結只有少數幾個,並且必須僅從這些繫結中選擇,這些繫結預設情況下是停用的,應該啟用它們才能獲得事務所需的必要支援。這些繫結如下:

  • NetTcpBinding
  • NetNamedPipeBinding
  • WSHttpBinding
  • WSDualHttpBinding
  • WSFederationHttpBinding

操作行為 - 繫結促進了事務傳播的路徑,而操作則負責事務處理以及操作配置。操作行為主要使用兩個屬性:TransactionFlow和TransactionScopeRequired。這裡需要注意的是,TransactionFlow主要有三個值:Allowed、Mandatory和NotAllowed。

以下程式碼顯示更改繫結和操作契約的配置是否會促進客戶端的傳播。

<bindings> 
   <wsHttpBinding> 
      <binding name = "MandatoryTransBinding" transactionFlow = "true"> 
         <reliableSession enabled ="true"/>
      </binding>
   </wsHttpBinding> 
</bindings>

事務協議

WCF使用三種類型的事務協議:

  • 輕量級
  • Ole事務
  • WS-Atomic事務(WS-AT)

在這三種協議中,WS-AT是一個可互操作的協議,它能夠跨防火牆進行分散式事務的流動。但是,當事務嚴格基於Microsoft技術時,不應使用此協議。

WCF事務的階段

WCF事務有兩個階段,如下圖所示。

Wcf Transaction Phases 1
  • 準備階段 - 在此階段,事務管理器檢查所有實體是否已準備好提交事務。

  • 提交階段 - 在此階段,實體的提交實際上開始了。

下圖說明了WCF事務這兩個階段的功能。

Wcf Transaction Phases 2

啟用WCF事務

為了成功啟用WCF事務,需要按順序執行一系列六個步驟。必要的步驟如下所述。

步驟1 - 建立兩個WCF服務

這方面的首要步驟是在WCF中構建兩個服務專案以參與單個事務。將在這兩個服務上執行資料庫事務,並且將瞭解WCF事務如何將它們統一起來。還建立了一個WCFTransactions的web應用程式,用於在單個事務範圍內使用這兩個建立的服務。

Wcf Transaction Enable 1

步驟2 - 方法建立及其使用TransactionFlow屬性的屬性

在這裡,將為這兩個WCF服務建立UpdateData方法,以便使用OperationContract屬性插入資料庫。為了完成此任務,首先使用ServiceContract屬性建立一個介面類。為了在新建立的方法中啟用事務,它使用TransactionFlow進行屬性設定,並使用is Allowed值允許事務。

[ServiceContract]
public interface IService1 {
   [OperationContract]
   [TransactionFlow(TransactionFlowOption.Allowed)]
   void UpdateData();
}

步驟3 - 使用TransactionScopeRequired屬性實現WCF服務

這是透過使用以下程式碼完成的:

[OperationBehavior(TransactionScopeRequired = true)]
public void UpdateData() {
   try {
      SqlConnection objConnection = new SqlConnection(strConnection);
      objConnection.Open();
      
      using(SqlTransaction transaction = Program.dbConnection.BeginTransaction()) {
     	   Boolean doRollback = false;
     	   using(SqlCommand cmd = new SqlCommand(
            "insert into Customer (Customer name, Customer code) values ('sss', 'sss')"objConnection))
         
     	   try {
            cmd.ExecuteNonQuery();
     	   } catch(SqlException) {
            doRollback = true;
            break;
     	   }
      }
      
      if(doRollback)
         transaction.Rollback();
      else
         transaction.Commit();  
   }
   finally {
      objConection.Close();
   }
}

步驟4 - 透過WCF服務配置檔案啟用事務流

其編碼如下:

<bindings>
   <wsHttpBinding>
      <binding name = "TransactionalBind" transactionFlow = "true"/>
   </wsHttpBinding>
</bindings>

必須將允許事務的繫結附加到端點才能公開WCF服務。

<endpoint address = "" binding = "wsHttpBinding" bindingConfiguration = "TransactionalBind" contract = "WcfService1.IService1">

步驟5 - 在單個事務中呼叫這兩個服務

在這裡,上述兩個服務在一個事務中被呼叫,為此,TransactionScope物件用於對這兩個服務進行分組。呼叫上述物件的Complete方法來提交WCF事務。要回滾,則應呼叫Dispose方法。

using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew)) {
   try {
      // Call your webservice transactions here
      ts.Complete();
   } catch (Exception ex) {
      ts.Dispose();
   }
}

下面顯示了將WCF事務在一個範圍內分組的完整程式碼的小片段:

using (TransactionScope ts = new TransactionScope(TransactionScopeOption.RequiresNew)) {
   try {
      ServiceReference1.Service1Client obj = newServiceReference1.Service1Client();
      obj.UpdateData();
      ServiceReference2.Service1Client obj1 = new ServiceReference2.Service1Client();
      obj1.UpdateData();
      ts.Complete();
   } catch (Exception ex) {
      ts.Dispose();
   }
}

步驟6 - 測試WCF事務

測試在第六個也是最後一步完成,在呼叫第一個WCF服務後,會強制出現異常。

Wcf Transaction Enable 2
廣告