WCF学习笔记之事务编程

WCF学习笔记之事务编程

一: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 = 20;
            model.Uid = 1;
            model.ID = 1;

            AccountModel OutModel = new AccountModel();
            OutModel.ID = 2;
            OutModel.Uid = 2;
            OutModel.Money = 1;

            using (ChannelFactory<ITransactionDemo> ChannelFactory = new ChannelFactory<ITransactionDemo>("TransactionAccount"))
            {
                ITransactionDemo proxy = ChannelFactory.CreateChannel();
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    proxy.AddAccount(model);
                    proxy.OutAccount(OutModel);
                    transactionScope.Complete();
                }
            }
复制代码

本文是学习[WCF全面解析]中有关事务编程的内容;针对WCF事务编程做一个简单的要点记录;

如果,您认为阅读这篇博客让您有些收获,不妨点击一下右下角的推荐】按钮。  因为,我的写作热情也离不开您的肯定支持。

感谢您的阅读,[源代码下载]

 
 
 
标签: WCF
原文地址:https://www.cnblogs.com/Leo_wl/p/3255061.html