【问题标题】:Unexpected transaction flow in WCF serviceWCF 服务中的意外事务流
【发布时间】:2013-11-29 12:42:01
【问题描述】:

我有一个典型的 WCF 4.0 服务,它使用 wsHttpBindingtransactionFlow="true" 设置:

[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
[FaultContract(typeof(Invalid))]
void DoWork();

这是我的服务器端实现:

[ServiceBehavior(
    ConcurrencyMode = ConcurrencyMode.Multiple,
    InstanceContextMode = InstanceContextMode.Single,
    TransactionIsolationLevel = IsolationLevel.Serializable,
    TransactionTimeout = "00:00:15",
    ReleaseServiceInstanceOnTransactionComplete = false
)]
public class MyService: IMyService {

    [OperationBehavior(TransactionScopeRequired = false)]
    public void DoWork() {
        if (System.Transactions.Transaction.Current == null)
            Trace.TraceInformation("WTF?!");
    }
}

和客户端调用:

channel.DoWork(); // `Transaction.Current` is null at server-side as expected

using (var tx = new TransactionScope()) {
    channel.DoWork(); // Transaction.Current is still null at server-side! :(
    // .......  
}

当我将 TransactionScopeRequired 更改为 true 时,我在服务器端得到了预期的分布式事务,但现在即使在没有外部范围的情况下调用也得到了它:

channel.DoWork(); // Transaction.Current is not null

最烦人的是,如果我返回Invalid 错误,它会回滚我的任何内部已完成 范围!这意味着尽管TransactionFlowOption.Allowed,在调用我的服务时我不得不始终使用显式事务范围。这是为什么呢?

我尝试将TransactionAutoComplete = false 添加到OperationBehavior 声明以希望解决问题,但得到了

System.InvalidOperationException: 合约上的操作“创建” 'IUserIdentityStore' 配置为 TransactionAutoComplete 设置为 false 并且 ConcurrencyMode 未设置为 Single。 TransactionAutoComplete 设置为 false 需要 ConcurrencyMode.Single。

这太荒谬了。

换句话说 - 当我返回声明的错误时,如何获得可选的事务流行为并且没有自动回滚?

【问题讨论】:

    标签: c# .net web-services wcf transactions


    【解决方案1】:

    TransactionScopeRequired 文档明确指出,如果 TransactionScopeRequired 为 false,则该方法将始终在没有事务的情况下执行。

    至于自动回滚的问题,如果TransactionAutoComplete设置为true,所有未处理的异常(Faults are Exceptions)确实会回滚事务,这是有道理的:分布式事务的这个参与者有问题,因此事务必须回滚。如果您说 Invalid fault 不是真正的错误,那么您应该使用另一种机制来指示成功或失败,例如从您的服务返回结果代码。

    接下来,您的服务定义对我来说似乎有点奇怪: InstanceContextMode 设置为 Single,这表明您的服务将是一个单例:您的服务将只有 1 个实例在运行。此外,ConcurrencyMode 设置为 Multiple,表示多个客户端可以同时使用单个实例。

    我建议您将 InstanceContextMode 设置为 PerCall 并将 ConcurrencyMode 设置为 Single,这将为每个客户端调用创建一个新的专用服务实例。 Code Project上有一篇关于 WCF 并发的优秀文章。

    【讨论】:

      猜你喜欢
      • 2010-11-26
      • 2011-10-09
      • 1970-01-01
      • 2010-12-18
      • 2011-11-23
      • 2011-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多