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
广告
© . All rights reserved.