鉴于我有一个Web / SOAP服务,如何为Rebus(消息传递总线)设置和拆除正确的事务上下文?当Rebus调用消息处理程序时,这不是问题,因为Rebus将在调用处理程序之前设置事务上下文 - 但是Web服务处理程序需要通过Rebus发送/发布消息的相反情况呢?
我对如何实现HTTP模块或类似模型不感兴趣 - 只有Rebus的基础知识:准备Rebus发送消息需要什么?
与应用程序数据库通信时,Web服务代码有自己的事务处理。我需要能够在设置数据库事务时设置Rebus,并在对数据库执行相同操作时设置comit / rollback Rebus。
我的独立命令行程序遇到类似问题,需要同时与数据库交互并发送Rebus消息。
答案 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模块,它也能正常工作;)