如何为Web服务设置Rebus事务上下文

时间:2016-11-03 13:02:38

标签: asp.net web-services transactions rebus

鉴于我有一个Web / SOAP服务,如何为Rebus(消息传递总线)设置和拆除正确的事务上下文?当Rebus调用消息处理程序时,这不是问题,因为Rebus将在调用处理程序之前设置事务上下文 - 但是Web服务处理程序需要通过Rebus发送/发布消息的相反情况呢?

我对如何实现HTTP模块或类似模型不感兴趣 - 只有Rebus的基础知识:准备Rebus发送消息需要什么?

与应用程序数据库通信时,Web服务代码有自己的事务处理。我需要能够在设置数据库事务时设置Rebus,并在对数据库执行相同操作时设置comit / rollback Rebus。

我的独立命令行程序遇到类似问题,需要同时与数据库交互并发送Rebus消息。

1 个答案:

答案 0 :(得分:1)

Rebus将自动在其自己的"环境事务上下文"中登记发送和发布操作,该操作通过静态(*)AmbientTransactionContext.Current属性访问。

如果您愿意,可以自己实施ITransactionContext,但Rebus在框中附带DefaultTransactionContext

你这样使用它:

using(var context = new DefaultTransactionContext())
{
    AmbientTransactionContext.Current = context;

    // send and publish things in here

    // complete the transaction
    await context.Complete();
}

可以轻松放入,例如在OWIN中间件或类似的东西。

(*)该属性是静态的,但底层值绑定到当前执行上下文(通过使用CallContext.LogicalGet/SetData),这意味着您可以将其视为线程绑定,具有良好的属性它按预期流向延续。

在Rebus 2.0.2中,可以通过AmbientTransactionContext.SetAccessors(...)Action<ITransactionContext>调用Func<ITransactionContext>来自定义用于获取/设置上下文的访问者。像这样:

AmbientTransactionContext.SetAccessors(
    context => {
        if (HttpContext.Current == null) {
            throw new InvalidOperationException("Can't set the transaction context when there is no HTTP context");
        }
        HttpContext.Current.Items["current-rbs-context"] = context
    },
    () => HttpContext.Current?.Items["current-rbs-context"] as ITransactionContext
);

在这种情况下,即使使用旧式学校的HTTP模块,它也能正常工作;)