WCF事务流程问题

发布于 2024-08-12 02:07:17 字数 720 浏览 1 评论 0原文

我想将 WCF 服务操作配置为在我的客户端发送事务时接受事务,但如果未发送事务则不创建事务。我认为这与 COM+ 中支持的事务属性类似。

有谁知道这是否可以通过 WCF 事务来完成?

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

以下是我认为我希望能够执行此操作的原因的示例:

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

服务A---->服务B----> <1 数据库更新>
|
V服务C----> <2 DB更新>

ServiceC 的 2 次数据库更新需要在根位于 ServiceC 上的事务内执行。服务 B 的单个数据库更新不需要在事务内进行。然而,ServiceA 定义了一个事务,要求 ServiceB 和 ServiceC 的数据库更新两次作为原子工作单元发生。

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

谢谢,

大卫·马德里安

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

淡墨 2024-08-19 02:07:17

我认为您无法获得您想要的确切行为。

原因是一个操作必须让 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 操作:一个是事务性的,一个不是。第一个可以由事务客户端调用,第二个可以在认为不需要事务时调用。服务本身将委托给相同的方法实现,因此不会出现代码重复。

I don't think you can get the exact behaviour you wish.

The reason is that one Operation must either have TransactionScopeRequired be true or false. So TransactionScopeRequired is not equivalent to the COM+ transaction settings. If you wish to flow the transaction then TransactionScopeRequired must be true. However that means that the operation will always create a transaction when it is invoked.

Option 1

What you could do is to supress the transaction if there is no distributed transaction:

        [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);
            }
        }

But that may violate your System.Transaction avoidance requirement. Plus it sort of smells. :)

Option 2

I know this isn't your question, but why can't service B always use a transaction? That would be my preference. It seems you don't want the overhead of a transaction since it is only one update call.

I can think of 2 reasons to have service B use a transaction:

  • Architectural consistency -- all services follow the same pattern. This makes the system easier to understand and also...
  • Maintainability -- if your system is easier to understand that also aids in maintainability. Also, if later you need to add a second update call to Service B the design already supports that with no changes.

Option 3

Another option would be to create 2 WCF Operations: one that is transactional and one that is not. The first could be called by transactional clients and the second when a transaction is deemed not necessary. The services themselves would delegate to the same method implementation so there would be no code duplication.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文