1. 程式人生 > >[WCF Transaction] 1. 基本概念

[WCF Transaction] 1. 基本概念

WCF 支援分散式事務,也就是說事務可以跨越服務、程序、機器邊界,在多個服務和客戶端間存在。

Single service/single resource transaction

uploads/200705/02_105023_wcftrans1.gif



Distributed transactional service-oriented application

uploads/200705/02_105028_wcftrans2.gif



Transaction Binding

只有 TCP-、 IPC- 以及 WS-related 等 Binding 支援事務。預設情況下,這些 Binding 並不會參與事務,需要我們顯示將 TransactionFlow 屬性設定為 true 才行。

NetTcpBinding tcpBinding = new NetTcpBinding( );
tcpBinding.TransactionFlow = true;


<bindings>
  <netTcpBinding>
    <binding name = "TransactionalTCP" transactionFlow = "true" />
  </netTcpBinding>
</bindings>


TransactionFlow 並不會在 Metadata 中釋出,也就是說我們同樣需要手動設定客戶端 Binding 的 TransactionFlow 屬性。

WSHttpBinding binding = new WSHttpBinding();
binding.TransactionFlow = true;

ChannelFactory<IContract> factory = new ChannelFactory<IContract>(binding,
  "http://localhost:8080/myservice");
IContract client = factory.CreateChannel();

using (client as IDisposable)
{
  using (TransactionScope scope = new TransactionScope())
  {
    client.Test();
    scope.Complete();
  }
}  


啟 用可靠性(Reliability)通訊有助於減少事務失敗的可能性,如果使用 NetTcpBinding、WSHttpBinding,建議做如下設定,以便啟用可靠性傳輸。而 NetNamedPipeBinding 和 WSDualHttpBinding 預設就是可靠性,則無需再做調整。

NetTcpBinding binding = new NetTcpBinding();
binding.ReliableSession.Enabled = true;


Transaction Protocols

WCF 使用不同的事務管理協議來控制事務執行範圍(execution scope)。

  • Lightweight: 僅能在同一程式域的上下文中傳遞事務,無法跨越程式域和服務邊界。只能在服務內部或外部適用,同時它也是效能最好的一種協議。不過這種協議似乎沒什麼用處,因為 WCF Framework 中沒有任何一種 Binding 支援此協議。
  • OleTx: 允許事務跨越程式域、程序或機器邊界。使用 RPC 呼叫,採取 Windows 專用二進位制格式。無法跨越防火牆,也不能和其他異種平臺進行整合。多用於 Windows 體系的 Intranet 環境。
  • WS-Atomic(WSAT): 和 OleTx 相似,同樣允許事務跨越程式域、程序或機器邊界。和 OleTx 不同,WSAT 是一種工業標準,採取 HTTP 協議,TEXT 編碼,可以跨越防火牆。雖然 WSAT 也能用於 Intranet,但多數時候它用於 Internet 環境。
NetTcpBinding tcpBinding = new NetTcpBinding( );
tcpBinding.TransactionFlow = true;
tcpBinding.TransactionProtocol = TransactionProtocol.WSAtomicTransactionOctober2004;


<bindings>
  <netTcpBinding>
    <binding name = "TransactionalTCP"
      transactionFlow = "true"
      transactionProtocol = "WSAtomicTransactionOctober2004"
      />
  </netTcpBinding>
</bindings>


Transactional Service

除了開啟 Binding 的事務支援外,我們還必須通過 TransactionFlow 和 TransactionScopeRequired 來控制服務是否參與和使用事務。

TransactionFlowAttribute 只能用於服務方法(Operation/Method)上,它允許我們進行不同的事務參與設定。有一點要注意,我們不能為 IsOneWay=true 的服務設定事務支援。

  • TransactionFlowOption.NotAllowed: 不參與任何事務。(預設值)
  • TransactionFlowOption.Allowed: 允許參與事務。也就是說,如果呼叫方(客戶端)和服務Binding啟用了事務,則參與。
  • TransactionFlowOption.Mandatory: 強制啟用事務。呼叫方(客戶端)和服務 Binding 必須啟用事務才能呼叫本服務。

"TransactionScopeRequired=true" 指示服務方法使用環境事務(ambient transaction)。

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

public class Service : IService
{
  [OperationBehavior(TransactionScopeRequired=true)]
  public void Test()
  {
    Transaction transaction = Transaction.Current;
    Debug.Assert(transaction == null);
  }
}


Transaction modes

我們可以將事務分為三種類型,分別是 Client/Service transaction、Client transaction、Service transaction。

1. Client/Service transaction,最常見的一種事務模型,通常由客戶端或服務本身啟用一個事務。

設定步驟:
(1) 選擇一個支援事務的Binding,設定 TransactionFlow = true。
(2) 設定 TransactionFlow(TransactionFlowOption.Allowed)。
(3) 設定 OperationBehavior(TransactionScopeRequired=true)。

2. Client transaction,強制服務必須參與事務,而且必須是客戶端啟用事務。

設定步驟:
(1) 選擇一個支援事務的Binding,設定 TransactionFlow = true。
(2) 設定 TransactionFlow(TransactionFlowOption.Mandatory)。
(3) 設定 OperationBehavior(TransactionScopeRequired=true)。

3. Service transaction,服務必須啟用一個根事務,且不參與任何外部事務。

設定步驟:
(1) 選擇任何一種Binding,設定 TransactionFlow = false(預設)。
(2) 設定 TransactionFlow(TransactionFlowOption.NotAllowed)。
(3) 設定 OperationBehavior(TransactionScopeRequired=true)。

----------

圖片選自《Programming WCF Service》。