具有自定义sqlconnection的NServicebus处理程序

具有自定义sqlconnection的NServicebus处理程序,nservicebus,sqlconnection,sqlcommand,Nservicebus,Sqlconnection,Sqlcommand,我有一个NServiceBus处理程序,可以创建新的sql连接和新的sql命令 但是,在整个过程完成之前,执行的命令不会提交到数据库 这就像在处理程序本身中有一个隐藏的sql事务 我将代码移动到一个自定义控制台应用程序中,没有使用nservicebus,sql命令立即执行并保存。与nservicebus不同,nservicebus直到处理程序结束时才保存。找到了解决方案 在我的连接字符串中,我必须添加Enlist=False实际上,每个处理程序都包装在一个事务中,默认事务保证依赖于DTC。这是故

我有一个NServiceBus处理程序,可以创建新的sql连接和新的sql命令

但是,在整个过程完成之前,执行的命令不会提交到数据库

这就像在处理程序本身中有一个隐藏的sql事务

我将代码移动到一个自定义控制台应用程序中,没有使用nservicebus,sql命令立即执行并保存。与nservicebus不同,nservicebus直到处理程序结束时才保存。

找到了解决方案


在我的连接字符串中,我必须添加Enlist=False

实际上,每个处理程序都包装在一个事务中,默认事务保证依赖于DTC。这是故意的:)

如果禁用它,则可能会收到重复的消息或丢失一些数据,因此必须小心操作。您可以使用端点配置API禁用事务,而不是使用连接字符串中的选项


在这里,您可以找到有关配置和可用保证的更多信息。

正如@wlabaj Setting englist=False所述,将确实确保在处理程序中打开的事务与传输用于接收/发送消息的事务不同

然而,需要注意的是,它改变了消息处理语义。默认情况下,使用DTC时,处理程序中的接收/发送和任何事务操作都将以原子方式提交/回滚。如果ENSTEL=False,则情况并非如此,因此可能会为同一消息提交多个处理程序事务。考虑下面的场景作为可能发生的示例情况:

  • 收到消息(开始传输事务)
  • 消息已在处理程序内成功处理(处理程序事务已成功提交)
  • 传输事务失败,消息被移回输入队列
  • 第二次收到消息
  • 消息已在处理程序内成功处理
在您的案例中,Enlist False设置的行为可能是一种可取的行为。话虽如此,我认为有必要澄清在消息处理语义方面的后果。

工作单元 消息应作为单个工作单元进行处理。不是每件事都成功就是失败

如果您希望执行多个工作单元,那么

  • 创建多个端点
  • 或者发送多条消息
这还有一个好处,即这些数据可以并行处理

请注意,创建多个处理程序不会产生这种效果。同一端点上的所有处理程序都将是同一工作单元的一部分

立即派遣 如果您确实希望发送特定的消息,而消息的发送不能是工作单元的一部分,则可以立即这样发送:

using (new TransactionScope(TransactionScopeOption.Suppress))
{
    var myMessage = new MyMessage();
    bus.Send(myMessage);
}
这对V5有效,对于其他版本,最好查看文档:

登记=false 这是一种解决方法,不能用于规避特定的事务配置,Tomasz对此做了很好的解释

这可能导致数据损坏,因为在错误恢复的情况下,可以多次处理相同的消息,然后再次执行相同的数据库操作