WCF交易流程问题

时间:2009-11-19 23:46:12

标签: wcf transactions distributed-transactions

我希望将WCF服务操作配置为在我的客户端发送一个事务时接受事务,但如果没有发送则不创建一个事务。我认为这与COM +中的Supported transaction属性类似。

有谁知道这是否可以通过WCF交易完成?

我试图通过使用WCF事务编程模型(例如,服务操作上的TransactionFlowAttribute和TransactionScopeRequired)而不是使用System.Transactions显式事务编程模型来实现这一切。

以下是我希望能够做到这一点的原因示例:

ServiceA实现了一个调用两个数据服务的高级业务操作。服务B中的操作执行单个数据库更新,而服务C中的操作执行两个数据库更新。

ServiceA ----> ServiceB ----> < 1 DB update>
     |
     V Service C ----> < 2 DB更新>

ServiceC的2个数据库更新需要在ServiceCl的根目录下执行。服务B的单个数据库更新不需要在事务中进行。但是,ServiceA定义了一个事务,该事务需要ServiceB和ServiceC的数据库更新两个作为原子工作单元发生。

我的问题是如何配置ServiceB,以便在ServiceA调用它时,它会在该事务中登记。但是,当直接调用ServiceB而不是通过服务A调用ServiceB时,它不需要在事务中运行,因为它只执行一次数据库更新。

谢谢,

David Madrian

1 个答案:

答案 0 :(得分:2)

我认为你不能得到你想要的确切行为。

原因是一个Operation必须要么TransactionScopeRequired为true或false。因此TransactionScopeRequired不等同于COM +事务设置。如果您希望流动事务,则TransactionScopeRequired必须为true。但是,这意味着操作将始终在调用时创建事务。

选项1

如果没有分布式事务,你可以做的是压制事务:

        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete=false)]
        public string GetData(int value)
        {            
            using (TransactionScope scope = GetTransaction())
            {
                string result = DoSQL();
                scope.Complete();

                return result;
            }
        }

        private TransactionScope GetTransaction()
        {
            Transaction ambientTransaction = Transaction.Current;

            if (ambientTransaction == null 
                || 
                ambientTransaction.TransactionInformation.DistributedIdentifier.Equals(Guid.Empty))
            {
                return new TransactionScope(TransactionScopeOption.Suppress);
            }
            else
            {
                return new TransactionScope(ambientTransaction);
            }
        }

但这可能违反了您的System.Transaction避免要求。再加上它有点味道。 :)


选项2

我知道这不是你的问题,但为什么服务B不能总是使用交易?那是我的偏好。看起来你不想要交易的开销,因为它只是一次更新调用。

我可以想到服务B使用交易的两个理由:

  • 架构一致性 - 所有服务都遵循相同的模式。这使得系统更易于理解,而且......
  • 可维护性 - 如果您的系统更易于理解,也有助于维护。此外,如果稍后您需要向服务B添加第二次更新调用,则设计已经支持该服务而无需更改。


选项3

另一个选择是创建2个WCF操作:一个是事务性的,另一个不是。第一个可以由事务客户端调用,第二个可以在认为不需要事务时调用。服务本身将委托给相同的方法实现,因此不会有代码重复。