EventSourcing和DDD实体事件

时间:2017-11-21 13:37:34

标签: events cross-domain domain-driven-design event-sourcing event-store

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

问题:阅读EventSourcing事件日志以进行审核。

问题:在更新/创建/删除实体时考虑所有这些事情的事件在EventStore中保存事件的最佳方法是:它们必须易于阅读,版本,可能不适用于这种情况但通常是粒状事件最好是域事件可能会用于跨域通信。

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

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

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

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

    根 - 管道。

    public class Pipeline : AggregateRoot<IPipelineState>
    

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

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

    所有馆藏都可以存储很多实体。现在我引发像PipelineCreatedEvent,PipelineChangedEvent这样的事件(不仅在管道改变时,甚至在添加,更新,删除状态或逻辑时)和PipelineRemovedEvent。

1 个答案:

答案 0 :(得分:4)

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

在您的情况下,尝试制定系统中发生的事情,而不是实体,但用商业词语:

  1. OrderCreated(orderId = 123)
  2. OrderItemAdded(orderId = 123,&#39; product1&#39;)
  3. OrderItemAdded(orderId = 123,&#39; product2&#39;)
  4. OrderItemRemoved(orderId = 123,&#39; product1&#39;)
  5. OrderPaid(orderId = 123)
  6. OrderArchived(orderId = 123)
  7. 这些事件发生在什么地方?使用Order,order是你的聚合根,123是它的aggregateId。你可能甚至不需要OrderItems,除非命令处理程序需要这样做(比如说,你不想为已经删除的项发出OrderItemRemoved事件)。

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

    重要的是要了解您的事件越具体业务性,您稍后将使用域聚合和读取模型获得更大的灵活性。请记住,您的活动是不可改变的,永远存在!

    OrderEntityChangedEvent (新状态=付费)表示您实体的特定结构 OrderPaid 事件除了在某处有订单聚合根之外什么都没有。