首页 > 解决方案 > 在 CQRS / 事件溯源中,是否所有数据都需要在命令和事件中?

问题描述

假设我有一个围绕 CQRS 事件溯源基础构建的应用程序:

  1. 由命令处理程序处理的应用程序调度命令 DTO
  2. 在传递和应用 Command 的数据时聚合引发事件
  3. 事件处理程序在收到他们感兴趣的事件时应用域逻辑和副作用(在我的情况下:他们进行预测)。

我的问题是:在步骤 1 和 3 中,我们是否需要在命令和事件 DTO 中提供所有信息,或者我们是否可以传递处理程序可以从数据库中获取的某些实体的 ID?

例子:

Employee Aggregate 有名字、姓氏、电子邮件和一些 VO,如地址、电话等。

它是Worker Entity的根,所以在我的应用程序的某个地方,我有一个 Employee Aggregate Id(UUID,生成的域)和 Worker Entity Id(整数,生成的数据库)的映射

指挥方:

在 RegisterEmployee 命令上,我是否需要传递为所有员工字段补充所需的所有数据?

然后我会有一个非常大的构造函数,其中包含名字、姓氏、电子邮件、地址、电话 1、电话 2 等。

我不能只给出命令中的基本字段(名字、姓氏、电子邮件)并传递 Worker 实体 ID,以便 RegisterEmployee 命令处理程序可以在数据库中检索要传递给聚合的电话和地址字段吗?

活动方:

在事件方面,如果我的 EmployeeRegistered 事件处理程序必须投影我的员工的读取模型,它是否需要拥有事件本身的所有信息才能构建读取模型?

或者我可以只将基本信息(名字、姓氏、电子邮件)和工作实体 ID 放入 EmployeeRegistered 事件的有效负载中,以便投影脚本本身加入数据库以检索一些复杂和隐藏的信息?

[编辑]

也许 RegisterEmployee 试图做太多事情,我应该:

  1. 发送一个简单的 RegisterEmployee 命令和基本的东西
  2. 调度其他一些命令,例如 AddEmployeeTelephone、AddEmployeeArress 等

但是在这种情况下,它是否违反了注册操作应该发生在同一事务中的原则?如果我的 RegisterEmployee 成功而其他人没有怎么办?我最终会得到一个不完整的员工注册流程吗?

[编辑 2]

嗨,博拉,你说得对。我的上下文发生在从遗留应用程序迁移到 cqrs 应用程序(至少某些部分)中。

所以我想让遗留应用程序做自己的事情,我只听数据库端的持久性事件,并从它们发送域命令。

这就是为什么我可以想象有一个命令持有“刚刚持久”的实体 ID,以便不复制命令中实体的字段,并减轻管道。

标签: domain-driven-designcqrsevent-sourcing

解决方案


域模型/设计中有问题。让我退后一步,概述理想的方式,以便您可以映射缺失的部分。

  • RegisterEmployee Command包含所有数据输入Employee Aggregate
  • Employee Application Service从前端接收命令
  • Employee Application Service初始化Employee Aggregate,最好借助工厂方法
  • Employee AggregateEmployeeRegistered Event在成功验证和构造新的 Employee 对象时引发
  • Employee Application ServiceEmployee Repository
  • EmployeeRegistered Event持久化事务成功后发送到消息代理
  • EmployeeRegistered Event包含订阅者所需的整个数据集
  • Subscribers对于这个事件可能在同一个限界上下文(BC)或不同的BC
  • Interested Subscribers赶上事件并Application Service在自己的BC中致电相关人员
  • Application services初始化基础设施服务并执行交易(在您的情况下,这些是预测)

事件处理程序中不应有域逻辑。


推荐阅读