积极答复者
[OperationBehavior(TransactionScopeRequired=true)]可否在没有事务流的情况下不创建新事务?

问题
答案
全部回复
-
Hi,
1.TransactionScopeRequired默认应该是false.
2.针对你的情况,确实适用于客户端事务模型,事务有客户端启动。JiYuan的说法是正确的。可以解决你的问题。
3.另外开发的时候注意,事务测试很容易出错,即使你配置正常,程序运行成功,也未必就能事务成功。这个问题在XP单机开发下很容易出现,你参考Ay.Xu在此论坛的帖子:如何在一个 Transaction 中执行两个 WCF 服务。
你对WCF4种事务模型先做个基本了解,然后在来解决自己的问题。这样的话就不会素手无策了。附带的是事务模型的介绍:
WCF事务范围可以涉及到客户端、服务端。当然这个取决于你项目具体的配置。在WCF的事务模式主要由绑定协议、事务流属性、事务范围属性决定。在WCF所有的绑定协议中不是所有的协议都支持事务。事务流属性TransactionFlowAttribute 只能用于服务方法(Operation/Method)上,它允许我们进行不同的事务参与设置。注意不能为 IsOneWay=true 的服务设置事务流支持:
TransactionFlowOption.NotAllowed: 不参与任何事务。(默认值)
TransactionFlowOption.Allowed: 允许参与事务。如果调用方(客户端)和服务Binding启用了事务,则参与。
TransactionFlowOption.Mandatory: 强制启用事务。调用方(客户端)和服务 Binding 必须启用事务才能调用本服务。这样综合作用,匹配的结果就是3种启动事务的模式。分别是:Client/Service transaction、Client transaction、Service transaction模式。他们分别的设置情况是:
【5.1】. Client/Service transaction,最常见的一种事务模型,通常由客户端或服务本身启用一个事务。设置步骤:
(1) 选择一个支持事务的Binding,设置 TransactionFlow = true。
(2) 设置 TransactionFlow(TransactionFlowOption.Allowed)。
(3) 设置 OperationBehavior(TransactionScopeRequired=true)。
【5.2】. Client transaction,强制服务必须参与事务,而且必须是客户端启用事务。设置步骤:
(1) 选择一个支持事务的Binding,设置 TransactionFlow = true。
(2) 设置 TransactionFlow(TransactionFlowOption.Mandatory)。
(3) 设置 OperationBehavior(TransactionScopeRequired=true)。
【5.3】. Service transaction,服务必须启用一个根事务,且不参与任何外部事务。设置步骤:
(1) 选择任何一种Binding,设置 TransactionFlow = false(默认)。
(2) 设置 TransactionFlow(TransactionFlowOption.NotAllowed)。
(3) 设置 OperationBehavior(TransactionScopeRequired=true)。
你也可以搜索资料,或者参考相关的书籍,一般都有介绍:
WCF分布式开发步步为赢(12):WCF事务机制(Transaction)和分布式事务编程
Frank.Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
老徐的博客:http://frank_xl.cnblogs.com -
Frank Xu Lei 列出的三种模式都决定了在服务端要开启一事务环境,可能是客户端的,也可能是服务端的。
但在服务端操作设计中不想强制要求一个环境事务。[OperationBehavior(TransactionScopeRequired=true)]这种情况下,如果客户端没有事务流,那么服务端也会要自动创建一个服务端的事务环境,但这正是我不想要的。也就是说在客户端有事务流的情况下,我需要客户端的事务范围,但如果客户端没有事务流的情况,我也不想在服务端有环境事务。
针对你的这个情况,我能给出的建议就是:
同一个服务定义两个版本,
1.一个是不启动事务的一般WCF服务;
2.一个是支持client事务模式的WCF服务;
两个服务在发布的时候,使用不同的终结点,客户端添加服务引用的代码不同。
生下来就是你在代码里判断了,如果有使用事务的需求,就调用支持client事务模式的客户端代理。
如果不需要就调用另外一个客户单代理。
Frank.Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
老徐的博客:http://frank_xl.cnblogs.com -
感谢所有参与回复的人。
看来我所说的问题已经清楚了,是的,大多数在进行服务接口设计都会考虑到是否需要事务,那么一般这个事务范围都是针对这服务接口内部是否需要而定的,往往没有考虑到外部客户端的使用情况,比如在一个服务接口汲及一系列同步更新数据操作,那么在设计之初会考虑要有事务范围,而有些服务接口在服务端角度来说根本不需要事务范围,但从客户端角度来说,它需要参与到事务范围之内,这就出现了一个问题:在设计服务接口时事务不单是服务端本身需要的,而有可能是客户端需要的。那么怎么办呢?一种可能像Frank Xu Lei所说那样列出两种版本,但这样代码成本可能要高很多。另一种我所想的就是,即然在服务接口设计之初无法决定客户端是否需要事务,那么就对每个可能需求事务的接口(例如汲及数据库读、改等)都加上[OperationBehavior(TransactionScopeRequired=true)],但也许这样会给性能造成一些副作用,因为有些接口可能根本不需要事务环境,而强制被要求存在于一个事务环境范围之内。