0

我目前正在使用 J Oliver 的 EventStore,我想知道如何在调用时检查聚合是否存在 (GetById(Guid id))?

按照 CQRS 的工作原理,我应该查询读取的数据库还是应该以某种方式找出 EventStore 中是否存在相应的聚合?

4

2 回答 2

3

目前 EventStore 的工作方式,如果找不到流,您将创建一个新的 Stream(聚合根)。

检查这一行: https ://github.com/joliver/CommonDomain/blob/master/src/proj/CommonDomain.Persistence.EventStore/EventStoreRepository.cs#L53

它在商店中调用此方法: https ://github.com/joliver/EventStore/blob/master/src/proj/EventStore.Core/OptimisticEventStore.cs#L45

调用此构造函数: https ://github.com/joliver/EventStore/blob/master/src/proj/EventStore.Core/OptimisticEventStream.cs#L27

效果是它将使用在持久性中找到的 Commit 填充 Stream,或者如果没有找到它,它将不做任何事情并返回新的 Stream。

但是,您不必问自己这个问题。一个命令应该在你发送它之前被验证。在发送命令之前,使用您的读取模型验证命令。

此外,命令和聚合根状态应该是足够的信息来执行您在域中的决定。这基本上意味着您必须在发送命令之前确定域状态以避免域中的异常。您可以为此使用读取模型。

更新作为对毛罗斯评论的回应:

您遇到并发问题。您可以使用偶尔连接的正在合并的系统中使用的方法来解决它。您可以做的是将 Stream 修订存储在读取模型中,以便您知道您对哪个 AR 修订进行了操作。然后,当命令被处理时,您就会知道您是否在处理 AR 的旧状态。

如果 AR 版本高于命令带来的版本,您可以将命令作为失败丢弃(悲观并发),或者您可以尝试合并更改。

这可以通过查看从命令中的修订到当前状态所产生的事件来完成。然后调用命令应该执行的行为并查看由该行为创建的事件并比较两个事件集合。如果没有任何冲突事件,您可以将新创建​​的事件提交到存储。如果有冲突,可以抛出并发异常。

我认为这是解决此类并发问题的最佳选择。

搜索事件合并以获取更多信息。

于 2012-01-31T16:06:15.763 回答
1

我猜你实际上指的IRepository.GetById()是 JOliver 的 CommonDomain 项目?

当您使用不在事件存储中的聚合根 ID 调用 GetById 时,存储库将为您提供一个具有 .Version == 0 和 .Id == Guid.Empty 的新聚合对象。我刚刚创建了自己的派生存储库,它检测到该条件并返回 null:

public override TAggregate GetById<TAggregate>(Guid id, int versionToLoad)
{
    var aggregate = base.GetById<TAggregate>(id, versionToLoad);
    return aggregate.Version > 0 ? aggregate : null;
}

这可能是错误的处理方式(请参阅 Mikael 的回答),但到目前为止它对我来说效果很好。

于 2012-01-31T17:22:17.187 回答