EventSourcing 和 DDD 实体事件

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

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

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

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

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

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

    根 - 管道。
    public class Pipeline : AggregateRoot<IPipelineState>
    

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

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

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

    最佳答案

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

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

  • 订单创建 (orderId=123)
  • OrderItemAdded (orderId=123, 'product1')
  • OrderItemAdded (orderId=123, 'product2')
  • OrderItemRemoved (orderId=123, 'product1')
  • 订单支付 (orderId=123)
  • OrderArchived (orderId=123)

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

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

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

    OrderEntityChangedEvent (new Status = Paid) 暗示您实体的特定结构
    已支付订单 除了某处有一个 Order Aggregate 根之外,事件不假设任何东西。

    关于EventSourcing 和 DDD 实体事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47414490/

    相关文章:

    domain-driven-design - 处理来自映射对象的实体更新

    c# - 为什么异常会传播出事件处理程序?

    接口(interface)中的 C# 事件 - 来自 vb.net 程序员的混淆

    javascript - iframe 中父级到子级的跨域访问

    javascript - 跨域通信

    domain-driven-design - 简洁的架构和 DDD 丰富的模型验证

    php - 通过紧密耦合其值对象摆脱实体工厂

    .net - 当用户单击 X(关闭程序)时,VB.NET 重载默认功能

    c++ - 在 "event.GetFrom(m_cpVoice)==S_OK"时调用函数(因此事件发生时)[SAPI 5.1 和 C++]

    node.js - CORS 调用后 Express session cookie 不会保留