我第一次使用NServiceBus并且有一个小而简单的应用程序,用户提交表单,表单字段然后被发送到队列,处理程序收集这些数据并使用linq-将其写入数据库到SQL。
对于DBA而言,组件服务中的任何更改都是完全禁止的,因此我现在正在寻找DTC的替代方法(在数据库服务器上未启用),但使用AsA_Server以便消息不要被清除。
我已尝试在IConfigureThisEndpoint之后删除AsA_Server并自行指定配置,但这似乎不起作用(控制台出现,页面加载但没有任何反应,它甚至不会在断点处停止。)AsA_Client确实有效,但是据我所知,消息将在启动时被清除,我需要避免。
有什么建议吗?
谢谢,
OMK
编辑:现在已经通过在一个禁止事务范围中包含对数据库的调用来解决这个问题,这允许数据库工作在没有环境事务的情况下完成:
using (TransactionScope sc = new TransactionScope(TransactionScopeOption.Suppress))
{
// code here
sc.Complete();
}
答案 0 :(得分:9)
使用AsA_Server时,您指定需要持久队列,并且需要配置事务队列。
使用事务发送/接收MSMQ要求您作为一个事务的一部分发送,传输,接收和处理。然而,实际上所有这些阶段都发生在他们自己的交易中。
例如,当发送方向其本地MSMQ子系统发送消息时,发送事务就完成了(即使队列地址是远程的,发送方仍然发送到本地队列,该队列充当远程队列的一种代理) )。
当发送方机器上的MSMQ子系统成功将消息发送到接收方机器上的MSMQ子系统时,传输事务完成。
即使这可能都发生在一台机器上,我猜你的Handle()方法正在写入另一台机器上的数据库。
这里的问题是,从事务角度来看,要使接收操作满意地完成,您对数据库的调用必须成功。只有这样,消息才会从输入队列中退出。这可以防止在处理失败期间消息丢失的任何可能性。
但是,为了在整个网络中强制执行,您需要让DTC协调分布式事务到数据库。
最重要的是,如果您想在分布式环境中使用持久队列,那么您将需要使用MSDTC。
希望这会有所帮助。
答案 1 :(得分:7)
还有另一种选择。在您的连接字符串中,您可以添加选项以不在分布式事务中登记,这将在DTC中忽略您的数据库连接。
当然,如果在配置中设置了这个,那么DTC将忽略应用程序的所有数据库事务,而不仅仅是特定的事务。
示例:
<add key="DatabaseConnectionString" value="Data Source=SERVERNAME;Initial Catalog=DBNAME;Integrated Security=True;Enlist=False"/>
答案 2 :(得分:6)
使用NServiceBus 4.0,您现在可以执行以下操作,最终对我有用:
Configure.Transactions.Advanced(t =>
{
t.DisableDistributedTransactions();
t.DoNotWrapHandlersExecutionInATransactionScope();
});
答案 3 :(得分:5)
当您使用As(AsA_Client,AsA_Server)接口时,配置将在Init()之后应用,因此您在那里创建的有关MsmqTransport和UnicastBus的所有设置都将被覆盖。
可以在IHandleProfile实现中使用IWantTheConfiguration覆盖这些设置。在应用默认角色之后但在总线启动之前,您将获得配置。
这样您就可以更改默认配置文件设置并根据需要定制它们:停用事务,启用模拟......
示例:
public class DeactivateTransactions : IHandleProfile<Lite>, IWantTheEndpointConfig
{
private IConfigureThisEndpoint configure;
public IConfigureThisEndpoint Config
{
get { return configure; }
set
{
this.configure = value;
Configure.Instance.MsmqTransport()
.PurgeOnStartup(false)
.IsTransactional(false); // Or other changes
}
}
public void ProfileActivated()
{
}
}