我有一个NServiceBus处理程序,它创建一个新的sql连接和新的sql命令。
但是,在整个过程完成之后,才会将执行的命令提交到数据库。
就像处理程序本身中存在隐藏的sql事务一样。
我将代码移动到没有nservicebus的自定义控制台应用程序中,并立即执行并保存了sql命令。与nservicebus不同,它不会在处理程序结束之前保存。
答案 0 :(得分:2)
事实上,每个处理程序都包含在一个事务中,默认的事务保证依赖于DTC。这是故意的:)
如果您禁用它,那么您可能会收到重复的消息或丢失一些数据,因此必须小心。您可以使用端点配置API禁用事务,而不是使用连接字符串中的选项。
您可以在此处找到有关配置和可用保证的更多信息http://docs.particular.net/nservicebus/transports/transactions。
答案 1 :(得分:0)
找到了解决方案。
在我的连接字符串中,我必须添加Enlist = False
答案 2 :(得分:0)
如@wlabaj所述,设置Enlist = False确实会确保处理程序中打开的事务与传输接收/发送消息所使用的事务不同。
然而,重要的是要注意它改变了消息处理语义。默认情况下,当使用DTC时,接收/发送和处理程序内的任何事务操作将以原子方式提交/回滚。使用Enlist = False并非如此,因此可能会为同一消息提交多个处理程序事务。将以下场景视为可能发生的示例案例:
Enlist-False设置的行为在您的情况下可能是理想的行为。话虽如此,我认为值得澄清一下消息处理语义的后果是什么。
答案 3 :(得分:0)
消息应作为单个工作单元处理。一切都成功或失败。
如果您想要执行多个工作单元,那么
这样做的好处是可以并行处理这些内容。
请注意,创建多个处理程序不会产生此效果。同一端点上的所有处理程序 将成为同一工作单元的一部分,从而进行交易。
如果你真的想发送一条特定的消息,当发送消息不能成为工作单元的一部分时,你可以立即发送它:
using (new TransactionScope(TransactionScopeOption.Suppress))
{
var myMessage = new MyMessage();
bus.Send(myMessage);
}
这对V5有效,对于其他版本,最好查看文档:
http://docs.particular.net/nservicebus/messaging/send-a-message#dispatching-a-message-immediately
这是一种解决方法,不得用于规避特定的事务配置,如Tomasz所解释的那样。
这可能导致数据损坏,因为在错误恢复的情况下可以多次处理相同的消息,然后再次执行相同的数据库操作。