一:WCF事務設置
事務提供一種機制將一個活動涉及的所有操作納入到一個不可分割的執行單元;
WCF通過System.ServiceModel.TransactionFlowAttribute特性定義在契約的相應操作方法上;
TransctionFlowOption三個選項:NotAllowed、Allowed、Mandatory不同的事務流轉策略;
1:NotAllowed(默認) 客户端的事務不會允許被流轉到服務端,服務端也不會試圖去接收流入的事務;
2:Allowed 如果客户端的事務在,則被流轉到服務端,服務端會試圖去接收流入的事務;
3:Mandatory 客户端必須在一個事務中進行服務調用,相應的事務會被流轉到服務端。服務端接收到的消息 中必須包含被序列化的事務;
[ServiceContract]
public interface IBankingService
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void Transfer(string fromAccountId, string toAccountId, double amount);
}
由於分佈式事務在客户端和服務端之間協調過程依賴於它們之間的相互消息交換,因此在一個單向(One-Way)
操作契約上不允許將應用在上面的TransctionFlowAttribute特性指定為:Allowed 或 Mandatory [P143]
二:事務與綁定的聯繫
支持事務綁定的除BasicHttpBinding(基於WS-I Basic Profile標準綁定)、NetMsmqBinding(只能採用單工的消息交換)、
MsmqIntegrationBinding(只能採用單工的消息交換) 其它都有事務的流轉能力;
支持事務的綁定流轉默認也是被關閉,要通過配置或者編程的方式開啓該選項;
WCF支持三種不同的事務處理協議:OleTx、WS-AT 1.0、WS-AT 1.1 分別對應於TransactionProtocol中的三個靜態只讀
屬性OleTransactions(與Default默認一樣)、WSAtomicTransationOctober2004、WSAtomicTransaction11
NetTcpBinding和NetNamedPipeBinding通過TransactionFlow設置支持事務的開關,TransactionProtocol設置事務協議;
WSHttpBinding、WSDualHttpBinding和WSFedrationHttpBinding支持協議WS-AT 1.0,而WS2007HttpBinding和
WS2007FederationHttpBinding支持協議WS-AT 1.1,它們僅僅只有TransactionFlow 沒有TransactionProtocol設置事務協議;
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="transactionalTcpBinding" transactionFlow="true"
transactionProtocol="WSAtomicTransactionOctober2004">
</binding>
</netTcpBinding>
<ws2007HttpBinding>
<binding name="transactionalHttpBinding" transactionFlow="true"></binding>
</ws2007HttpBinding>
</bindings>
<services>
<service name="Service.WithdrawService">
<endpoint binding="customBinding"
bindingConfiguration="transactionalTcpBinding"
contract="Service.Interface.IWithdrawService" />
</service>
<service name="Service.DepositService">
<endpoint binding="customBinding"
bindingConfiguration="transactionalHttpBinding"
contract="Service.Interface.IDepositService" />
</service>
</services>
</system.serviceModel>
</configuration>
三:通過服務(操作)行為控制事務
通過服務契約確定事務流轉的策略,通過事務綁定實施事務的流轉;通過服務操作設置提交方式及是否自動登記到事務之中
服務操作OperationBehaviorAttribute兩個事務管理相關的屬性:TransactionAutoComplete 和 TransactionScopeRequired
1:TransactionAutoComplete(默認值Flase) 表示相應操作的執行是否自動納入一個事務中;
2:TransactionScopeRequired(默認值true) 表示如果執行過程沒有拋出異常,完成後將自動提交事務;
public class BankingService : IBankingService
{
[OperationBehavior(TransactionScopeRequired = true)]
public void Transfer(string fromAccountId, string toAccountId, double amount)
{
}
}
四:事務相關的服務行為
ServiceBehaviorAttribute定義的4個與事務相關的屬性;
1:TransactionIsolationLevel:事務的隔離級別,默認值為IsolationLevel.Seriallizable;
2:TransactionTimeout 以字符串形式定義事務的超時時限;
3:TransactionAutoCompleteOnSessionClose 在會話正常結束(沒有異常)之後是否自動提交或完成開啓的事務,默認值False
4:ReleaseServiceInstanceOnTransactionComplete 當事務完成之後是否要將服務實例釋放掉,默認值False
[ServiceBehavior(TransactionIsolationLevel=IsolationLevel.ReadCommitted,TransactionTimeout="00:05:00",
TransactionAutoCompleteOnSessionClose=true)]
public class WithdrawService : IWithdrawService
{
[OperationBehavior(TransactionScopeRequired = true)]
public void Withdraw(string accountId, double amount)
{
}
}
注意:若契給服務ServiceBehavior定義的那些屬性後 若在其內的操作沒有一個設置OperationBehavior(TransactionScopeRequired = true)則會報錯;
也可以使用配置方式:
<service name="Service.DepositService" behaviorConfiguration="transactionBehavior">
<endpoint binding="customBinding"
contract="Service.Interface.IDepositService" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="transactionBehavior">
<serviceTimeouts transactionTimeout="00:30:00"/>
</behavior>
</serviceBehaviors>
</behaviors>
在事務流轉的場景中,流入的事務和目標服務的事務隔離級別必須一致;否則會報異常;客户端調用代碼如下;
沒有定義事務的級別則採用默認隔離級別Serializable;
using System.ServiceModel;
using Service.Interface;
using System.Transactions;
namespace TransactionalService.Client
{
class Program
{
static void Main(string[] args)
{
using (ChannelFactory<IBankingServicee> channelFactory = new ChannelFactory<IBankingServicee>("bankingservice"))
{
IBankingServicee bankingservice = channelFactory.CreateChannel();
using (TransactionScope transactionScope = new TransactionScope())
{
bankingservice.Transfer();
transactionScope.Complete();
}
}
}
}
}
五:事務實例:
接下來將通過一個簡單的事實來介紹一下WCF事務;因為比較簡單所以後面直接提供源代碼的下載[源代碼裏面還包括其它信息]:
1:首先是契約的定義:
using System.ServiceModel;
using System.Runtime.Serialization;
using Service.Model;
namespace Service.Interface
{
[ServiceContract(SessionMode=SessionMode.Required)]
public interface ITransactionDemo
{
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void AddAccount(AccountModel model);
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void OutAccount(AccountModel model);
}
}
2:契約服務的實現內容
using Service.Interface;
using Service.Model;
using System.Data.Common;
using System.ServiceModel;
using Service.DAL;
using System.EnterpriseServices;
using System.Transactions;
namespace Service.ServerDeom
{
[ServiceBehavior(TransactionIsolationLevel = IsolationLevel.Serializable,
TransactionTimeout = "00:05:00",
TransactionAutoCompleteOnSessionClose = true)]
public class TransactionDemoService:ITransactionDemo
{
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
public void AddAccount(AccountModel model)
{
try
{
AccountDAL.Update(model);
}
catch (Exception ex)
{
throw new FaultException(new FaultReason(ex.Message));
}
}
[OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = false)]
public void OutAccount(AccountModel model)
{
try
{
AccountDAL.Update(model);
}
catch (Exception ex)
{
throw new FaultException(new FaultReason(ex.Message));
}
}
}
}
3:宿主服務的配置
<bindings>
<netTcpBinding>
<binding name="portSharingBinding" portSharingEnabled="true"></binding>
</netTcpBinding>
<ws2007HttpBinding>
<binding name="transactionalTcpBinding" transactionFlow="true" />
</ws2007HttpBinding>
</bindings>
<services>
<service name="Service.ServerDeom.TransactionDemoService">
<endpoint address="http://127.0.0.1:3724/ExcptDivideService"
binding="ws2007HttpBinding"
bindingConfiguration="transactionalTcpBinding"
contract="Service.Interface.ITransactionDemo"/>
</service>
</services>
4:客户端的配置信息
<endpoint name="TransactionAccount" address="http://127.0.0.1:3724/ExcptDivideService"
binding="ws2007HttpBinding"
contract="Service.Interface.ITransactionDemo"/>
5:客户端的實現代碼:
AccountModel model = new AccountModel();
model.Money = 25;
model.Uid = 1;
model.ID = 1;
AccountModel OutModel = new AccountModel();
OutModel.ID =10;
OutModel.Uid = 2;
OutModel.Money = 1;
using (ChannelFactory<ITransactionDemo> ChannelFactory = new ChannelFactory<ITransactionDemo>("TransactionAccount"))
{
ITransactionDemo proxy = ChannelFactory.CreateChannel();
using (TransactionScope transactionScope = new TransactionScope())
{
try
{
proxy.AddAccount(model);
throw new Exception();
proxy.OutAccount(OutModel);
transactionScope.Complete();
}
catch (Exception ex)
{
(proxy as ICommunicationObject).Abort();
}
}
本文是學習[WCF全面解析]中有關事務編程的內容;針對WCF事務編程做一個簡單的要點記錄;