0

我能够使用 Rhino Service Bus 和 Sql Server Express 创建一个测试应用程序。我有一个 MVC 4 前端,它创建一条消息并将其发送到队列,并在我的数据库表中创建一条记录。我有一个 Windows 服务,它从队列中获取消息并写入单独的数据库表。我希望消息发送/数据库写入是全部或全部。例如,如果消息发送或数据库写入失败,我希望能够将它们都回滚。我尝试将它们都包装在 TransactionScope 中,但根据我的测试,即使没有调用 scope.Complete,消息也会发送到队列。

这可能吗?如果是这样,有人可以指出我正确的方向吗?

仅供参考...队列是 MSMQ 事务队列

谢谢。

4

2 回答 2

1

我在 Rhino Service Bus Google Groups 网站上发布了同样的问题,并得到了 Oren 的回复。事实证明 RSB 可以处理事务,但我使用的是 IOnewayBus,它不使用 DTC。我进行了更改以使用 IStartableServiceBus,现在一切都按预期工作。

于 2013-07-23T17:59:11.857 回答
0

我们遇到了 Rhino 服务总线的问题,即所有事务都被隐式地登记到环境事务 (MSDTC) 中。这暂时没问题,但我们运行了许多长时间运行的进程,这些进程将花费超过一小时(DTC 的最大超时为一小时)。为了解决这个问题,我创建了一个 IMessageModule 的实现,如下所示:

/// <summary>
/// alows commands to opt-in to ambient transaction (MSDTC)
/// </summary>
/// <remarks>will supress by default</remarks>
public class SuppressAmbientTransactionMessageModule : IMessageModule
{

    [ThreadStatic]
    private static TransactionScope transactionScope;

    public void Init(ITransport transport, IServiceBus serviceBus)
    {
        transport.MessageArrived += TransportOnMessageArrived;
        transport.BeforeMessageTransactionCommit += transport_BeforeMessageTransactionCommit;
        transport.BeforeMessageTransactionRollback += transport_BeforeMessageTransactionCommit;
    }

    public void transport_BeforeMessageTransactionCommit(CurrentMessageInformation currentMessageInformation)
    {
        if (!(currentMessageInformation.Message is IWithAmbientTransaction))
        {
            transactionScope.Dispose();
        }
    }

    public void Stop(ITransport transport, IServiceBus bus)
    {
        transport.MessageArrived -= TransportOnMessageArrived;
        transport.BeforeMessageTransactionCommit -= transport_BeforeMessageTransactionCommit;
        transport.BeforeMessageTransactionRollback -= transport_BeforeMessageTransactionCommit;
    }

    public bool TransportOnMessageArrived(CurrentMessageInformation currentMessageInformation)
    {
        if (!(currentMessageInformation.Message is IWithAmbientTransaction))

        {
            transactionScope = new TransactionScope(TransactionScopeOption.Suppress);
        }
        return false;
    }
}

我还创建了一个名为 IWithAmbientTransaction 的无方法接口,以使特定命令能够加入环境事务。虽然拥有如此长时间运行的进程并不理想,但这种方法已经解决了我们长期运行事务的直接问题

于 2013-09-27T07:44:25.923 回答