在CQRS /事件来源中,是否所有数据都需要存储在“命令和事件”中?

时间:2019-08-09 07:37:40

标签: domain-driven-design cqrs event-sourcing

假设我有一个基于CQRS事件源基础的应用程序:

  1. 由命令处理程序处理的应用程序分派命令DTO
  2. 传递和应用Command的数据时,聚集引发事件
  3. 事件处理程序在接收到感兴趣的事件时会应用域逻辑和副作用(在我的情况下:它们是投影)。

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

示例:

  • 我有一个员工汇总
  • RegisterEmployee 命令
  • 已注册员工事件

Employee Aggregate具有名字,姓氏,电子邮件以及一些VO,例如地址,电话等。

它是工作人员实体的根,所以在我的应用程序中,我有一个员工聚合ID(UUID,生成域)和工作人员实体ID(整数,数据库生成)的映射

命令端:

在RegisterEmployee命令上,我是否需要传递所有需要充填所有Employee字段的数据?

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

我不能仅在命令中提供基本字段(名字,姓氏,电子邮件)并传递工作人员实体ID,以便RegisterEmployee命令处理程序可以在数据库中检索电话和地址字段以传递来汇总吗?

事件侧:

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

或者我可以只将基本信息(名字,姓氏,电子邮件)和工作人员实体ID放入EmployeeRegistered事件的有效负载中,以便投影脚本自己在数据库中进行某种联接以检索一些复杂的隐藏信息吗? >

[编辑]

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

  1. 用基础知识发送一个简单的RegisterEmployee命令
  2. 调度其他命令,例如AddEmployeeTelephone,AddEmployeeAdrress等

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

[编辑2]

嗨,波拉,您说的没错。我的上下文发生在从旧版应用程序到cqrs一个(至少某些部分)的迁移中。

因此,我想让旧版应用程序做自己的事情,所以我只侦听db端的持久性事件,并从它们中调度域命令。

这就是为什么我可以想象有一个命令持有“仅持久”实体ID,以便不重复该命令中实体的字段并减轻负担。

1 个答案:

答案 0 :(得分:2)

领域模型/设计中的某些功能已关闭。让我退后一步,勾勒出理想的方法,以便您可以绘制缺失的部分。

  • RegisterEmployee Command包含Employee Aggregate
  • 的所有数据输入
  • Employee Application Service从Frontend接收命令
  • Employee Application Service初始化Employee Aggregate,最好在工厂方法的帮助下进行
  • Employee Aggregate在成功验证和构造新的Employee对象时引发EmployeeRegistered Event
  • Employee Application ServiceEmployee Repository
  • 的帮助下保留了新的Employee对象。 成功执行持久性事务后,
  • EmployeeRegistered Event被调度到消息代理
  • EmployeeRegistered Event包含订户所需的整个数据集
  • 此事件的
  • Subscribers可以在相同的有界上下文(BC)中,也可以在不同的BC中。
  • Interested Subscribers赶上活动并在自己的BC中呼叫相关的Application Service
  • Application services初始化基础结构服务并执行交易(在您的情况下,这是预测)

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