WCF - 交易


WCF 中的事务是遵循某些属性的一组操作,统称为 ACID。在这里,如果单个操作失败,整个系统就会自动失败。当在线下订单时,就会发生交易。以下示例有助于更简单地理解交易过程。

例子

假设您从在线商店订购了一台液晶电视,并且您将使用信用卡支付金额。当您输入下订单所需的信息时,两个操作会同时发生。

一是从您的​​银行帐户中扣除指定的金额,二是将相同的金额存入供应商帐户。这两个操作都必须成功执行才能成功完成交易。

WCF 事务属性

WCF 事务遵循的四个属性如下:

  • Atomics性- 在事务完成时,所有操作必须充当单个不可分割的操作。

  • 一致性- 无论操作集是什么,系统始终处于一致性状态,即事务的结果始终符合预期。

  • 隔离- 在交易完成之前,系统的中间状态对外部世界的任何实体都是不可见的。

  • 耐用性- 无论发生任何类型的故障(硬件、断电等),都会维持提交的状态

配置 WCF 事务时,需要考虑一些因素。这些都是绑定和操作Behave。

绑定- WCF 中支持事务的绑定只有少数,仅从这些绑定中进行选择至关重要,这些绑定默认情况下保持禁用状态,应启用以获得事务所需的支持。这些绑定如下 -

  • NetTcp绑定
  • 网络命名管道绑定
  • WSHttp绑定
  • WSDualHttpBinding
  • WSFederationHttpBinding

操作Behave- 虽然绑定促进了事务传播的路径,但操作负责事务处理以及操作配置。操作Behave主要使用两个属性:TransactionFlow 和 TransactionScopeRequired。这里需要注意的是,TransactionFlow主要有三个值,分别是:Allowed、Mandatory、NotAllowed。

下面的代码显示了改变绑定和操作合约的配置是否有利于客户端的传播。

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

交易协议

WCF 使用三种类型的协议进行事务 -

  • 轻的
  • 奥莱交易
  • WS-Atomics事务 (WS-AT)

在这三者中,WS-AT 是一种可互操作的协议,支持跨防火墙的分布式事务流。但是,当事务严格基于 Microsoft 技术时,不应使用此协议。

WCF 事务的阶段

WCF 事务有两个阶段,如下图所示。

Wcf 事务阶段 1
  • 准备阶段- 在此阶段,事务管理器检查所有实体是否准备好提交事务。

  • 提交阶段- 在这个阶段,实体的承诺实际上开始。

下图说明了 WCF 事务两个阶段的功能。

Wcf 事务阶段 2

启用 WCF 事务

要成功启用 WCF 事务,需要按顺序执行一系列六个步骤。下面讨论必要的步骤。

步骤 1 - 创建两个 WCF 服务

这方面最重要的一步是在 WCF 中构建两个服务项目来参与单个事务。数据库事务将在这两个服务上执行,并且将了解它们如何通过 WCF 事务统一。还创建了 WCFTransactions Web 应用程序,以在单个事务范围内使用这两个创建的服务。

Wcf 事务启用 1

步骤 2 - 方法创建及其使用 TransactionFlow 属性的归属

在这里,将为两个 WCF 服务创建一个 UpdateData 方法,以使用 OperationContract 属性插入数据库。为了完成此任务,首先在 ServiceContract 属性的帮助下创建一个接口类。为了在新创建的方法中启用事务,它归因于 TransactionFlow,并且使用“允许”值允许事务。

[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 事务启用 2