一、事务传播概述
WCF可以跨越服务边界传递事务。这可以让服务参与到客户端事务里,客户端还可以在同一个事务里调用多个服务。客户端本身不一定是WCF服务。客户端事务是否传播到服务端可以通过绑定和操作契约契约的设置来控制。
我们把能够支持客户端事务传播给服务端的绑定称为“事务感知”型绑定。
只有TCP、IPC和WS绑定支持事务传播。
二、事务流与绑定
默认情况下,事务感知型绑定并不会传播事务。服务宿主或管理员必须明确设置服务接收进入的跨越组织或业务边界的事务。
为了支持事务传播。就必须在服务端和客户端绑定上明确设置允许传播事务。
所有的事务感知型绑定都提供了一个布尔型Transactionlow属性:
public class NetTcpBinding : Binding, IBindingRuntimePreferences{ // 如果启用事务流,则为 true;否则为 false。默认值为 false。 [DefaultValue(false)] public bool TransactionFlow { get; set; } // ......}为了启用事务传播,只需将属性设置为true即可。可以通过代码或配置文件进行设置。对于TCP绑定,如下:
代码:
NetTcpBinding binding=new NetTcpBinding();binding.TransactionFlow=true;配置文件:
严格来说,事务不需要启用可靠消息。事务会依赖自己的机制实现可靠性。但是,启用可靠性会降低事务中断的可能性,它会尽量保证通信可靠,这意味着事务不大可能因为通信问题而中断。因此,最佳做法就是在NetTcpBinding和WsHttpBinding支持事务的时候,启用可靠性传输。
二、事务流与契约操作
使用事务感知型绑定并启用事务流,并不意味着服务想在每个操作里使用客户端事务或客户端让事务优先传播。
这种服务级别的决策应该是客户端 与服务端之间协商约定的一部分。因此,WCF提供了TransactionFlowAttribute属性,它可以控制客户端事务是否传播给服务端。
public sealed class TransactionFlowAttribute : Attribute, IOperationBehavior{ public TransactionFlowAttribute(TransactionFlowOption transactions); // 一个 System.ServiceModel.TransactionFlowOption,指示是否支持传入事务。 public TransactionFlowOption Transactions { get; }}public enum TransactionFlowOption{ // 事务不应成为流。这是默认值。 NotAllowed = 0, // 事务可以成为流。 Allowed = 1, // 事务必须成为流。 Mandatory = 2,}注意,TransactionFlow属性标记在方法层级上,因为WCF坚持事务流应该在操作级别决定,而不是在服务级别决定:
public class MyService : IMyService{ [TransactionFlow(TransactionFlowOption.Allowed)] public void MyMethod() { }}这是为了达到方法级别参与客户端事务的粒度而精心设计的。
TransactionFlow属性会包含在服务发布的元数据中,所以当你引用服务契约定义时,定义将会包含这个TransactionFlow值。WCF将会让你在服务端实现的操作时上应用TransactionFlow属性:
[ServiceContract]public interface IMyService{ [OperationContract] void MyMethod();}public class MyService : IMyService{ [TransactionFlow(TransactionFlowOption.Allowed)] public void MyMethod() { }}但是,这种用法并不值得鼓励,因为它会分割即将发布的逻辑服务契约定义代码。
TransactionFlowOption.NotAllowed
禁止参与事务。
当操作配置为禁止传播事务流时,客户端不能传播到服务端。即使客户端发起一个事务且绑定允许传播,服务也会忽略事务流。服务永远不会使用客户端事务,且服务和客户端可以选择任意绑定并使用任意配置。TransactionFlowOption.NotAllowed是TransactionFlowOption的默认值。
TransactionFlowOption.Allowed
允许参与事务,如果调用方启用了事务,则参与。
当操作配置为允许传播事务时,如果客户端包含事务,服务将允许跨越边界传播客户端事务。但是,即使客户端传播了事务,服务也不一定必须使用这个事务。当使用TransactionFlowOption.Allowed时,服务可以配置使用任意绑定。无论是否为事务感知型绑定都可以,但是客户端与服务端绑定配置要兼容。当服务端绑定配置了允许事务流时,客户端可以传播也可以不传播事务。
TransactionFlowOption.Mandatory
强制参与事务,调用方必须启用事务才能调用本服务。
当操作配置为TransactionFlowOption.Mandatory时,服务和客户端必须使用事务感知型绑定,并启用事务传播。WCF会在服务加载是校验这些设置。对于强制事务流,客户端事务会一致传播给服务。但是 ,服务可以选择参与或不参与客户端事务。
ServiceBehaviorAttribute
描述服务参与事务的一些参数。
- TransactionAutoCompleteOnSessionClose = bool:指示当会话(Session)结束时是否自动提交事务(Complete); 这个属性和服务对象实例模式紧密相关,使用的时候,应该着重小心。
- ReleaseServiceInstanceOnTransactionComplete = bool:指示事务提交后是否释放服务实例对象;TransactionIsolationLevel= System.Transactions.IsolationLevel:用于指示事务隔离级别。
- OperationBehaviorAttribute:描述契约方法如何参与事务的一些参数
- TransactionScopeRequired = bool:该属性是 WCF 分布事务所必需的。它表明服务方法必须在事务范围(transaction scope)内执行。如果不添加该标记,则意味着服务方法不参与到事务中。
- TransactionAutoComplete = bool: 指示方法正常结束后是否自动提交事务。
三、单调
客户端可以传播事务到 服务端,当然也允许服务端根据需要终止客户端。但是,在单调操作中,客户端无法传递事务流到客户端,因为调用消息不包含应答消息。
[ServiceContract]public interface IMyService{ [OperationContract(IsOneWay=true)] [TransactionFlow(TransactionFlowOption.Allowed)] //错误操作 void MyMethod();}