EventSourcing 和 DDD 实体事件

Ive*_*tev 4 events domain-driven-design cross-domain event-sourcing

我有一个使用 EventSourcing 的 DDD 项目。目前有许多聚合根,其中许多都有实体的集合。甚至更多 - 一些实体具有其他实体的集合。

问题:出于审计目的读取 EventSourcing 事件日志。

问题:当实体被更新/创建/删除时,在 EventStore 中保存事件的最佳方法是什么,记住所有这些事情:它们必须易于阅读,版本,可能不适合这种情况,但通常粒度事件更可取,可能域事件将用于跨域通信。

  1. 我是否应该在根流中将整个根以及其中的所有实体集合保存为 RootChangedEvent ?

  2. 我是否应该只将根流中已更新/创建/删除的实体保存为 EntityChangedEvent/EntityCreatedEvent/EntityRemovedEvent

  3. 我应该在根流中保存两个事件 - 一个用于根 - RootChangedEvent 只有版本属性 + 第二个用于实体,如果在 EntityChangedEvent 或整个实体中更改,则只有一个属性,如果 EntityCreatedEvent 或只有 id 如果 EntityRemovedEvent (如何处理实体的实体是否创建/更新/删除?)

这是我项目中的一个例子:

根 - 管道。

public class Pipeline : AggregateRoot<IPipelineState>
Run Code Online (Sandbox Code Playgroud)

它有实体集合 - public IList<Status> Statuses.

每个状态都有实体的集合 - public IList<Logic> Logics

所有集合都可以存储很多实体。现在我会引发诸如 PipelineCreatedEvent、PipelineChangedEvent 之类的事件(不仅在 Pipeline 更改时,甚至在添加、更新、删除状态或逻辑时)和 PipelineRemovedEvent。

Rom*_*min 5

任何给定的聚合都应该有一个事件流,以避免竞争条件。聚合是一个事务边界。

在您的情况下,尝试用商业术语而不是实体来表述系统中发生的事情:

  1. 订单创建 (orderId=123)
  2. 添加订单项(订单 ID=123,'product1')
  3. 添加订单项(订单 ID=123,'product2')
  4. OrderItemRemoved (orderId=123, 'product1')
  5. 订单支付 (orderId=123)
  6. OrderArchived (orderId=123)

这些事件是怎么发生的?使用 Order 所以 order 是您的聚合根,而 123 - 它的aggregateId。您甚至可能不需要 OrderItems ,除非命令处理程序需要这样做(例如,您不想为已删除的项目发出 OrderItemRemoved 事件)。

您将有一个用于aggregateRoot 123 的事件流,并且在您处理PayOrder 命令时,没有人可以添加和OrderItem。

重要的是要了解,您的事件越具有特定的业务,您以后使用域聚合和读取模型的灵活性就越大。请记住,您的事件是不可变的,并且会永远存在!

OrderEntityChangedEvent (new Status = Paid) 意味着您的实体的特定结构 OrderPaid事件假设除了某处有一个 Order Aggregate 根之外什么都不做。