Postgresql 在与Entity Framework Core 3.0相结合的TransactionScope中登记Rebus,无需两阶段提交
我正在使用实体框架核心和PostgreSQL。我想在DbContext中重写SaveChanges,以提交EF更改并在同一数据库事务中发送带有Rebus的消息。该计划还将PostgreSQL用于传输等,但我在使用下面的代码仅在事务范围中登记REBU时遇到了困难Postgresql 在与Entity Framework Core 3.0相结合的TransactionScope中登记Rebus,无需两阶段提交,postgresql,entity-framework-core,rebus,Postgresql,Entity Framework Core,Rebus,我正在使用实体框架核心和PostgreSQL。我想在DbContext中重写SaveChanges,以提交EF更改并在同一数据库事务中发送带有Rebus的消息。该计划还将PostgreSQL用于传输等,但我在使用下面的代码仅在事务范围中登记REBU时遇到了困难 public override int SaveChanges() { using (var tx = new TransactionScope(TransactionScopeAsy
public override int SaveChanges()
{
using (var tx = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
tx.EnlistRebus();
var result = base.SaveChanges();
//TODO: _bus.Send("something happened");
tx.Complete();
return result;
}
}
运行上述操作会导致PostgresException:55000:已准备好的事务被禁用
,这是正确的,因为我的PostgreSQL配置没有启用它。我的问题是为什么Rebus需要在这里导致两阶段提交。也许我遗漏了一些东西,尽管我希望不需要2PC,因为实体框架和REBS都将使用相同的关系数据库实例
对EnstractReBus
的调用位于Rebus.TransactionScopes包中,不知道正在使用什么传输实现,可能会执行安全操作
是否有另一种方法可以在不进行两阶段提交的情况下以事务方式执行数据库操作和Rebus发送?当然,我可以使用一个单独的表来存储来自SaveChanges
的挂起消息,并从该表中提取一个单独的工作程序,然后使用Rebus发送消息。我怀疑这种方法是最可靠和最直接的
我使用的是Rebus 6.3.0、Rebus.PostgreAql 7.1.0、Rebus.TransactionScopes 6.0.0、Npgsql 4.1.3.1、Npgsql.EntityframeworkCore.PostgreSQL 3.1.4和EF Core 3.1.4。Rebus.PostgreSQL实际上会在没有Rebus.TransactionScopes的情况下自行登记到环境事务中 看看Rebus.PostgreSQL回购协议,我发现有一个公关似乎解决了我的问题。从公共关系中引用,网址: 我第一次尝试开始工作,但使用postgresql传输似乎没有任何效果 为了验证它确实在环境事务中发布消息,我做了以下修改:
public override int SaveChanges()
{
using (var tx = new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted },
TransactionScopeAsyncFlowOption.Enabled))
{
var result = base.SaveChanges();
_bus.Send(new MyMessage { CurrentDateTime = DateTime.Now}).Wait();
if (ShouldCrash)
{
throw new ArgumentException();
}
tx.Complete();
return result;
}
}
如果ShouldCrash
设置为true
,则不会发布任何消息,也不会对实体进行任何更改。如果ShouldCrash
设置为false
则执行消息发布和实体更改
我认为这是因为Npgsql文档中有以下内容:
请注意,如果在环境事务中打开和关闭与同一数据库的连接,而不同时打开两个连接,Npgsql将在内部重用同一连接,从而避免升级为完整的分布式事务