WCF能够跨越服务边界传递事务。这可让服务参与到客户端事务里,客户端还能够在同一个事务里调用多个服务。客户端自己不必定是WCF服务。客户端事务是否传播到服务端能够经过绑定和操做契约契约的设置来控制。ui
咱们把可以支持客户端事务传播给服务端的绑定称为“事务感知”型绑定。spa
只有TCP、IPC和WS绑定支持事务传播。设计
默认状况下,事务感知型绑定并不会传播事务。服务宿主或管理员必须明确设置服务接收进入的跨越组织或业务边界的事务。code
为了支持事务传播。就必须在服务端和客户端绑定上明确设置容许传播事务。对象
全部的事务感知型绑定都提供了一个布尔型Transactionlow属性:blog
public class NetTcpBinding : Binding, IBindingRuntimePreferences { // 若是启用事务流,则为 true;不然为 false。默认值为 false。 [DefaultValue(false)] public bool TransactionFlow { get; set; } // ...... }为了启用事务传播,只需将属性设置为true便可。能够经过代码或配置文件进行设置。对于TCP绑定,以下:事务
代码:get
NetTcpBinding binding=new NetTcpBinding(); binding.TransactionFlow=true;配置文件:io
<netTcpBinding> <binding transactionFlow="true" /> </netTcpBinding>严格来讲,事务不须要启用可靠消息。事务会依赖本身的机制实现可靠性。可是,启用可靠性会下降事务中断的可能性,它会尽可能保证通讯可靠,这意味着事务不大可能由于通讯问题而中断。所以,最佳作法就是在NetTcpBinding和WsHttpBinding支持事务的时候,启用可靠性传输。class
<netTcpBinding> <binding transactionFlow="true"> <reliableSession enabled="true"/> </binding> </netTcpBinding>
使用事务感知型绑定并启用事务流,并不意味着服务想在每一个操做里使用客户端事务或客户端让事务优先传播。
这种服务级别的决策应该是客户端 与服务端之间协商约定的一部分。所以,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(); }