none
[OperationBehavior(TransactionScopeRequired=true)]可否在没有事务流的情况下不创建新事务? RRS feed

  • 问题

  • [OperationBehavior(TransactionScopeRequired=true)]可否在没有事务流的情况下不创建新事务?
    服务的操作是否有环境事务,需要由客户端来控制。而不是在没有客户端事务流的情况下还要创建新事务。不知道怎么样去实现?
    谢谢。
    2009年7月9日 2:14

答案

  • 按照客户端有事务时服务器端才有事务,客户端没有时则没有事务的要求,说明服务器端不可能成为事务的根对象,那么服务器端只能是参与投票的嵌套事务。而.net提供的参与机制只有3种Required、RequiredNew和Suppress。其中没有一种是当根对象有事务时参与事务,没有事务时不参与事务。故您提到的场景可能.net不支持。个人分析,仅供参考。
    • 已标记为答案 wyssoft 2009年7月10日 2:26
    2009年7月9日 15:32

全部回复

  • 直接删除这个就可以达到你说得效果
    答案900, 目标五颗星
    2009年7月9日 2:57
  • 请采用client事务模型,具体步骤:
    1、为绑定启用事务流
    2、在操作契约中设置TransactionFlowOption.Mandatory
    3、将操作行为TransactionScopeRequired设为True
    2009年7月9日 3:25
  • 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
    2009年7月9日 4:36
    版主
  • 谢谢大家的回复。
    看来我还是没有说清楚。
    在[OperationBehavior(TransactionScopeRequired=true)]这种情况下,如果有客户端事务流服务端就会用客户端的事务流,如果没有呢系统就会在服务端默认创建了一个新事务。这种情况我知道,可是问题是在没有客户事务流的情况下,我也不想让服务端默认创建一个新事务。也就是说在服务端操作中我不想约定它一定要有事务范围或没有事务范围,而具体有没有事务范围就看客户端的调用是否提供了事务范围。
    2009年7月9日 9:30
  • 对阿,wcf中的client事务模式就是用来处理您所描述的情况,这是一个组合条件,要达到您的要求不仅仅看OperationBehavior一个特性。
    您所描述的现有的现象正好是client/service事务模型,请检查一下,您发布的操作契约是不是TransactionFlowOption.Allowed.而要满足您的要求就要改为TransactionFlowOption.Mandatory。其它设置都不变,这正是client事务模型。
    Frank.Xu把所有的事务模式都列举出来,供您参考。
    2009年7月9日 10:06
  • Frank Xu Lei 列出的三种模式都决定了在服务端要开启一事务环境,可能是客户端的,也可能是服务端的。
    但在服务端操作设计中不想强制要求一个环境事务。[OperationBehavior(TransactionScopeRequired=true)]这种情况下,如果客户端没有事务流,那么服务端也会要自动创建一个服务端的事务环境,但这正是我不想要的。也就是说在客户端有事务流的情况下,我需要客户端的事务范围,但如果客户端没有事务流的情况,我也不想在服务端有环境事务。
    2009年7月9日 11:09
  • 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
    2009年7月9日 13:12
    版主
  • Sorry,理解错误。
    wcf并没有提供四种以外的事务模型,故请按需求场景出发,重新考虑一下您的接口设计,看看在什么情况下使用事务或不使用事务更合理。
    2009年7月9日 13:28
  • 按照客户端有事务时服务器端才有事务,客户端没有时则没有事务的要求,说明服务器端不可能成为事务的根对象,那么服务器端只能是参与投票的嵌套事务。而.net提供的参与机制只有3种Required、RequiredNew和Suppress。其中没有一种是当根对象有事务时参与事务,没有事务时不参与事务。故您提到的场景可能.net不支持。个人分析,仅供参考。
    • 已标记为答案 wyssoft 2009年7月10日 2:26
    2009年7月9日 15:32
  • 感谢所有参与回复的人。

    看来我所说的问题已经清楚了,是的,大多数在进行服务接口设计都会考虑到是否需要事务,那么一般这个事务范围都是针对这服务接口内部是否需要而定的,往往没有考虑到外部客户端的使用情况,比如在一个服务接口汲及一系列同步更新数据操作,那么在设计之初会考虑要有事务范围,而有些服务接口在服务端角度来说根本不需要事务范围,但从客户端角度来说,它需要参与到事务范围之内,这就出现了一个问题:在设计服务接口时事务不单是服务端本身需要的,而有可能是客户端需要的。那么怎么办呢?一种可能像Frank Xu Lei所说那样列出两种版本,但这样代码成本可能要高很多。另一种我所想的就是,即然在服务接口设计之初无法决定客户端是否需要事务,那么就对每个可能需求事务的接口(例如汲及数据库读、改等)都加上[OperationBehavior(TransactionScopeRequired=true)],但也许这样会给性能造成一些副作用,因为有些接口可能根本不需要事务环境,而强制被要求存在于一个事务环境范围之内。

    2009年7月9日 15:52
  • Sorry,理解错误。
    wcf并没有提供四种以外的事务模型,故请按需求场景出发,重新考虑一下您的接口设计,看看在什么情况下使用事务或不使用事务更合理。

    没有关系,谢谢支持。
    2009年7月10日 2:25