我目前正在使用J Oliver的EventStore,我想知道如何在进行通话时检查聚合是否存在(GetById(Guid id))?
遵循CQRS如何工作,我应该查询读取数据库还是应该以某种方式找出EventStore中是否有相应的聚合?
TIA
JD
答案 0 :(得分:3)
EventStore目前的工作方式,如果找不到流,您将创建一个新的Stream(Aggregate root)。
它在商店中调用此方法: https://github.com/joliver/EventStore/blob/master/src/proj/EventStore.Core/OptimisticEventStore.cs#L45
效果是它将使用在持久性中找到的提交来填充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的回答),但到目前为止它对我来说还不错。