CQRS / EventStore:如何检查聚合是否存在?

时间:2012-01-31 15:36:17

标签: cqrs event-store

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

遵循CQRS如何工作,我应该查询读取数据库还是应该以某种方式找出EventStore中是否有相应的聚合?

TIA

JD

2 个答案:

答案 0 :(得分:3)

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

检查此行: 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

效果是它将使用在持久性中找到的提交来填充Stream,或者如果没有找到它将无效并返回新的流。

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

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

更新作为对Mauros评论的回应:

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

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

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

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

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

答案 1 :(得分:1)

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

当您使用不在事件存储中的聚合根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的回答),但到目前为止它对我来说还不错。