none
如何在一个 Transaction 中执行两个 WCF 服务 RRS feed

  • 问题

  • 相信这一定是个普通问题,但是查了很多资料后还是无法事先。
    我有两个service OrderHeaderUpdate 和 OrderLineUpdate,Service OrderHeaderUpdate  更新订单头,service OrderLineUpdate 更新订单明细。为确保一致性两个服务放在一个 transacton 中。参照 Juval Lowy <<WCF 服务编程>>我的配置如下:
    1. binding
    IIS 6.0 host service, web.config(部分)
    <endpoint address="" binding="wsHttpBinding" contract="WCF.IBarcode" bindingConfiguration="wsHttpBindingWS">
    <wsHttpBinding>
            <binding name="wsHttpBindingWS" transactionFlow ="true">          
              <security mode="None">
                <transport clientCredentialType="None" />
                <message establishSecurityContext="false" />
              </security>
            </binding>
          </wsHttpBinding> 
    2. 接口声明:
        <OperationContract()> _
        <TransactionFlow(TransactionFlowOption.Allowed)> 
    3. 服务声明:
       <OperationBehavior(TransactionScopeRequired:=True)> _
    4. 客户端 Winform 调用服务代码:
       Using tr As New TransactionScope
                Using DataSvc As New ServiceReferenceBarcode.BarcodeClient
                        DataSvc.OrderHeaderUpdate(orderHeaderDataTable)
                        DataSvc.OrderLineUpdate(orderLineDataTable)
                End Using
                tr.Complete()
        End Using

    执行单步调试时发现,当运行到 DataSvc.OrderHeaderUpdate(orderHeaderDataTable)时,还没等tr.complete(),数据库中 orderheader 表已经被更新了。
    单步调试并打印LocalIdentifier、DistributedIdentifier。(Console.WriteLine("Local ID: {0}, DTC id: {1} ", tns.TransactionInformation.LocalIdentifier.ToString, tns.TransactionInformation.DistributedIdentifier.ToString)),LocalIdentifier 是有值的,但是 DistributedIdentifier 一直为空,所以 transaction 好象根本没有传到 IIS 上的 WCF。我已经在客户端和 IIS 服务器上都启用 MSDTC,并允许 inbound/outbound call。

    请哪位已经实现过 WCF transaction 的高手帮忙看看,哪个环节可能出问题了?

    Ay
    2009年7月6日 9:58

答案

  • 花了1-2天时间在网上搜索资料,终于搞定了!
    现把过程简略帖出来与大家共享:
    1. 选择支持事务的绑定,我用的是 wsHttpBinding
    2. 在配置文件(web.config)的绑定设置中 transactionFlow ="true"
    3. 在服务接口中设定方法属性:<TransactionFlow(TransactionFlowOption.Mandatory)> 
    4. 在服务类中设定方法属性:<OperationBehavior(TransactionScopeRequired:=True)>
    5. 在客户端的 Winform UI 中使用代码:
        using tr as new transaction
            call_service_a()
            call_service_b()
    tr.complete()
        end using
    6. 配置 MSDTC,请参考 http://msdn.microsoft.com/zh-cn/library/ms752261.aspx
    7. 配置 MS-AT,请参考 http://www.cnblogs.com/walkinhill/archive/2007/05/26/565020.html
    第一次配置和使用 MSDTC 和 MS-AT 非常耗时间,幸运的是最终还是成功了。现在如果不提交 tr.complete(),更新是不会提交到的,数据库数据不会更新。同时我用 “服务跟踪查看器”跟踪,发现除了第一个更新时间比较慢(约1秒),后续的更新和不使用 transaction 的时间相当(约15毫秒),所以感觉使用 transaction 对性能没什么影响。
    我的环境:WCF 由 Win2003 IIS6 host,客户端是 xp,vsts2008开发。
    有一点奇怪的是,调试过程中我用 windump 没有截获 MS-AT 协议包,好象只有一次成功截获,我的 MS-AT 使用端口 10443 SSL,难道 SSL包无法截获,应该是可以的,比较奇怪。
           

    Ay
    • 已标记为答案 Ay Xu 2009年7月8日 9:13
    2009年7月8日 9:11

全部回复

  • Hi,
       一起讨论吧,我以前在做WCF事务编程的时候也遇到类似的问题。当时为了写WCF事务机制的文章,自己写的Demo,遇到了事务无法执行的问题。当时测试的事务代码页是使用客户端、服务端事务模式,客户端启动事务,分别调用两个服务。
    代码都是在本地,结果测试也是事务执行不能成功。自托管,使用netTCPBinding,尝试了很久无法解决。
       后来只能是代码在一个服务的操作里实现进行的事物测试。你现在遇到的问题我确实也很想知道。因为早期在Enterprise Service 和.net transactions里对事物的支持和测试很容易实现。但是在wcf 里我确实也遇到了麻烦。
      今天你提出的问题,和你一起讨论一下,看看能有什么好的解决方案~
    Frank.Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    老徐的博客:http://frank_xl.cnblogs.com
    2009年7月6日 11:42
    版主
  • 你好,

    可以参考下面的例子:
    http://msdn.microsoft.com/en-us/library/ms751413.aspx

    例子代码路径为:
    Basic\Service\Behaviors\Transactions\
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    2009年7月8日 3:11
    版主
  • 花了1-2天时间在网上搜索资料,终于搞定了!
    现把过程简略帖出来与大家共享:
    1. 选择支持事务的绑定,我用的是 wsHttpBinding
    2. 在配置文件(web.config)的绑定设置中 transactionFlow ="true"
    3. 在服务接口中设定方法属性:<TransactionFlow(TransactionFlowOption.Mandatory)> 
    4. 在服务类中设定方法属性:<OperationBehavior(TransactionScopeRequired:=True)>
    5. 在客户端的 Winform UI 中使用代码:
        using tr as new transaction
            call_service_a()
            call_service_b()
    tr.complete()
        end using
    6. 配置 MSDTC,请参考 http://msdn.microsoft.com/zh-cn/library/ms752261.aspx
    7. 配置 MS-AT,请参考 http://www.cnblogs.com/walkinhill/archive/2007/05/26/565020.html
    第一次配置和使用 MSDTC 和 MS-AT 非常耗时间,幸运的是最终还是成功了。现在如果不提交 tr.complete(),更新是不会提交到的,数据库数据不会更新。同时我用 “服务跟踪查看器”跟踪,发现除了第一个更新时间比较慢(约1秒),后续的更新和不使用 transaction 的时间相当(约15毫秒),所以感觉使用 transaction 对性能没什么影响。
    我的环境:WCF 由 Win2003 IIS6 host,客户端是 xp,vsts2008开发。
    有一点奇怪的是,调试过程中我用 windump 没有截获 MS-AT 协议包,好象只有一次成功截获,我的 MS-AT 使用端口 10443 SSL,难道 SSL包无法截获,应该是可以的,比较奇怪。
           

    Ay
    • 已标记为答案 Ay Xu 2009年7月8日 9:13
    2009年7月8日 9:11
  • Hi,
       不错,你的经验很有参考价值~
    呵呵我估计自己不成功,很有可能就是MSDTC和MS-AT 的问题。我当时也是出现事务失败但是数据一样更改。
    呵呵
    Frank.Xu Lei--谦卑若愚,好学若饥
    专注于.NET平台下分布式应用系统开发和企业应用系统集成
    Focus on Distributed Applications Development and EAI based on .NET
    老徐的博客:http://frank_xl.cnblogs.com
    2009年7月8日 12:11
    版主
  • Learning...

    2009年7月15日 15:46