我对使用JOliver's Event Store的单个交易中的多个聚合更新提出疑问。据我所知,每个聚合都应该有自己的事件流。现在,虽然许多命令处理程序只会加载一个聚合并只更新该聚合(即保存那些聚合的事件),但我可以想象会有一些命令处理程序需要更新多个聚合。当然,我想以交易方式做到这一点。
但是,我不知道如何使用Event Store做到这一点。通过在事件流上调用CommitChanges()
来完成存储事件。如果我们要更新多个聚合,则会有多个事件流,因此会多次调用CommitChanges()
。制作该事务的唯一方法是将其包装在TransactionScope
中,但这没有多大意义,因为底层存储技术可能不支持事务。所以我最终得到了这个代码,这绝对不是我想要的:
Guid aggregateGuid1 = Guid.NewGuid();
Guid aggregateGuid2 = Guid.NewGuid();
Guid commitGuid = Guid.NewGuid();
var stream = store.OpenStream(aggregateGuid1, 0, int.MaxValue);
stream.Add(new EventMessage() { Body = new MonitorDisabled { MonitorGuid = aggregateGuid1, User = "A" } });
stream.CommitChanges(commitGuid);
stream = store.OpenStream(aggregateGuid2, 0, int.MaxValue);
stream.Add(new EventMessage() { Body = new MonitorEnabled { MonitorGuid = aggregateGuid2, User = "B" } });
// Can't commit twice with the same commit id, what if fails after first one? No way for the store to know it had to write the second part of the commit.
stream.CommitChanges(commitGuid);
这让我觉得我完全错过了应该如何使用Event Store的东西。有人可以帮帮我吗?非常感谢!
答案 0 :(得分:8)
Aggregate定义了一个事务边界。
如果您需要执行交叉汇总交易,您应该检查您的聚合并重新设计它们。
如果操作(命令)影响多个聚合,并且您确信您的聚合设计得很好并且映射到域中的实际一致性边界,eventual consitency可能就是您要查找的内容。只需向每个聚合发送一个命令,并有两个事务,每个事务一个。如果你觉得最终的一致性不适合你的情况,那么我担心它会回到绘图板上。
答案 1 :(得分:3)
我不能代表约翰奥利弗,但我认为答案是“不要”。聚合是事务边界。如果您需要协调多个聚合的提交,则需要一个明确的协调过程,如saga,它将执行并在必要时撤消相关事件。
答案 2 :(得分:0)
如果您的基础架构支持分布式事务,有时可以更轻松地利用分布式事务。
TransactionScope与EventStore:
默认情况下,EventStore会抑制创建的任何环境事务 在提交对数据库的更改之前由NServiceBus提供。但是如果 您正在使用支持分布式的队列和数据库 事务(MSMQ,SQL Server,Raven等)然后你可以改变 EventStore的TransactionScopeOption是必需的。这将确保这一点 EventStore在环境事务中登记,其中包括 使用MSDTC以及消息队列和数据库进行分发 将保持同步。 - NES Documentation
与RavenDB交叉文档交易:
你会从我死去的,冷酷的,破碎的手中撬开交易 - Ayende