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 事务的两个阶段的功能。
启用 WCF 事务
要成功启用 WCF 事务,需要按顺序执行一系列六个步骤。下面将讨论必要的步骤。
步骤 1 − 创建两个 WCF 服务
在这方面,最重要的步骤是在 WCF 中构建两个服务项目以参与单个事务。数据库事务将在这两个服务上执行,并且将了解如何通过 WCF 事务将它们统一起来。还创建了一个 WCFTransactions 的 Web 应用程序,以在单个事务范围内使用这两个创建的服务。
步骤 2 − 方法创建及其使用 TransactionFlow 属性的归属
在这里,将为两个 WCF 服务创建一个 UpdateData 方法,以使用 OperationContract 属性将其插入数据库。为了完成此任务,首先在 ServiceContract 属性的帮助下创建一个接口类。为了在新创建的方法中启用事务,它被赋予 TransactionFlow 属性,并使用 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 事务
测试在第 6 步也是最后一步进行,在调用第一个 WCF 服务后,强制发生异常。