我想总结一下我对CQRS / ES的了解。我不久前开始阅读这个主题,因为我是年轻的开发人员,所以我不了解这个概念的各个方面。我将尝试在一些示例流程中描述我对CQRS的理解。因此,定义该架构的一般步骤,我们遵循以下流程:
用户向我们的控制器发出请求。在该控制器方法中,我们创建指定的命令(例如 CreateOrder )并将其传递给处理程序。
全局消息总线(或处理程序)负责将命令路由到指定的命令处理程序。所以我们将命令传递给 CreateOrderHandler
在处理程序中,我们创建聚合根(在本例中为 OrderAggregate ),然后我们应用 EventStore 中的所有事件。在EventStore中,我们只保留与指定聚合相关的事件数据(由全局id定义)。因此,在此步骤之后,我们在当前状态下进行聚合。
当我们创建聚合时,我们传递给它我们的命令和方法我们werify如果命令可以执行。如果我们可以运行此命令,我们会创建事件(在本例中为 OrderCreated )。
如果有任何异常我们在EventStore中保存了事件(我认为使用NoSql DB和简单的保存事件很简单)
现在处理程序将已保存的事件传递给我们的 Denormalizer 类,该类是创建查看模型的网关。因此,如果denormalizer获得一些事件,它会在我们的应用程序中更新/创建所有ViewModel。我们将ViewModel保存在单独的数据库中。
用户可以查询更新的视图模型。
所以我这是我对CQRS / ES理解的简化版。请在每一层都纠正我。我的问题是:
如果我们在DB中保存这个聚合,我们在第4步创建了聚合?保持现状。我在这里错过了什么吗?我们创建聚合只是为了检查创建事件的可能性?
我应该有实体吗?如果我在第5步中正确,我可以更新聚合实体并在我的视图模型中使用它们。我在这里有最大的困惑。
感谢所有答案;)
答案 0 :(得分:3)
如果我们在DB中保存这个聚合,我们在第4步创建了聚合? 保持现状。我在这里错过了什么吗?我们创造了 聚合仅用于检查创建事件的可能性?
如果您使用EventStore,ES本身会保留聚合的状态。你谈论"创造"在命令处理程序中聚合,但通常最好说在命令处理程序中聚合从ES重新补充。
Aggregate使用ES中应用的命令(或其数据)和引发(域)事件来跟踪聚合的状态更改,并且事件处理程序(如denormalizer)处理相同的事件。
在通常描述的流程中,我在步骤3之前进行了命令验证步骤。 无论如何,前段时间我试图描绘components of a typical CQRS/ES flow;网上有几个,但也许它可能有用
答案 1 :(得分:0)
聚合状态源自应用于它的过去事件。因此,您不需要存储它从事件流派生的状态。说过你可能想要创建快照以避免很长的事件历史记录。在设计快照系统之前,值得测试重新应用先前事件列表的速度。
当您向聚合发出命令时,它会分两个阶段处理它。第一阶段基本上检查它可以运行。如果是这样的话,它会构建一个或多个事件来表示变化,然后再将它们应用到它自己身上。关键在于事件的产生可以并且经常需要域逻辑的应用。换句话说,它不仅仅是一个事件制作者。
如果您觉得有帮助,我会在博客上详细介绍典型的CQRS应用程序。您可以在此处找到它:CQRS – A Step-by-Step Guide to the Flow of a typical Application