1

I would like to configure WCF service operations to accept a transaction if my client sends one, but not to create one if none is sent. I think this would be similar to the Supported transaction attribute in COM+.

Does anyone know whether this can be accomplished with WCF transactions?

I am trying to accomplish this all by using the WCF transaction programming model (e.g. TransactionFlowAttribute and TransactionScopeRequired on service operations) rather than using the System.Transactions explicit transaction programming model.

Here's an example of why I think I want to be able to do this:

ServiceA implements a high-level business operation which invokes two data services. An operation in Service B does a single database update and an operation in Service C does two database updates.

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

ServiceC's 2 database updates need to be performed within a transaction with its root on ServiceC. Service B's single database update does NOT need to take place within a transaction. However, ServiceA defines a transaction that requires ServiceB and ServiceC's database updates two happen as an atomic unit of work.

My question is how I can configure ServiceB so that when it's invoked by ServiceA it enlists in that transaction. However, when ServiceB is invoked directly rather than through Service A it does not need to run within a transaction because it's only doing one database update.

Thanks,

David Madrian

4

1 回答 1

2

我认为您无法获得所需的确切行为。

原因是一项操作必须让 TransactionScopeRequired 为真或假。所以 TransactionScopeRequired 不等同于 COM+ 事务设置。如果您希望处理事务,则 TransactionScopeRequired 必须为真。但是,这意味着该操作在调用时将始终创建一个事务。

选项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 使用事务的 2 个原因:

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


选项 3

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

于 2009-11-20T03:46:50.767 回答