我是CQRS/ES世界的新手,我有一个问题。我正在开发一个使用事件源和CQRS的发票web应用程序。
我的问题是--据我理解,进入系统的一个新命令(比如ChangeLineItemPrice)应该通过域模型来验证,这样它就可以被验证为合法命令(例如,检查这个行项目是否真的存在,价格不违反任何业务规则等等)。如果一切顺利(命令未被拒绝),则创建和存储适当的事件(例如,LineItemPriceChanged)。
在尝试应用命令之前,我没有完全理解的是,首先如何将这个聚合保存在内存中。如果系统中有一百万张发票,那么每次要应用命令时,是否都要播放整个历史记录?我是否总是在没有任何验证的情况下保存事件,并在构造视图模型/投影时进行验证?
如果我误解了这个过程的任何部分,我会感谢你的反馈。
谢谢你的帮忙!
发布于 2015-07-16 19:48:02
你不是一个人,这是一个常见的误解。让我首先回答验证部分:
在这种系统中有两种类型的验证。第一类是查找有效的电子邮件地址、仅为数字字段或必需字段的类型。这种类型甚至在发出命令之前就完成了。不应将包含此类问题的命令作为命令(对于带带和大括号,您可以在域侧检查,但这不是域问题,最好只是防止这种情况)。
下一种类型的验证是当是一个域关注点的时。这可能是你提到的那种东西,你检查价格是否在一组指定的参数之内。这是一个领域概念,业务人员将理解,做,并能够清楚地表达。
下一个阶段是由域应用状态更改并引发关联事件。然后,这些内容将被持久化,并在成功之后发布给应用程序的其余部分。
所有这些都可以通过内存中的聚合来完成。这些操作与处理该命令的域服务协调。它加载聚合,apply的所有过去事件(或加载快照),然后发出命令。命令成功后,它将请求所有未提交的新事件,并尝试持久化它们。一旦成功,它就会发布新事件。
正如您所看到的,它只加载特定聚合的事件。即使发生了很多事件,这个过程也是闪电般的快。如果性能是一个问题,有一些策略,比如将聚合保存在内存或快照中,您可以应用这些策略。
关于验证事件的最后一点。因为它们只能由您的聚合生成,所以它们是可信的。
如果您想了解更多细节,请查看我对CQRS和ES 这里的概述。看看我关于如何构建聚合根这里的文章。
祝你好运--我希望他们能帮上忙!
发布于 2015-11-23 16:03:10
正确的做法是,您必须重播事件,以“补充”域聚合。但是你不必为所有的发票重播所有的事件。如果将根聚合的实体id存储在事件中,则只需选择并重播具有相关id的事件。
那么,如何找到相关的聚合根id呢?其中一个读取存储库应该包含根据一组搜索标准获取id的相关信息。
https://stackoverflow.com/questions/31461546
复制相似问题