EventSourcing和DDD实体事件

EventSourcing和DDD实体事件,events,cross-domain,domain-driven-design,event-sourcing,Events,Cross Domain,Domain Driven Design,Event Sourcing,我有一个使用EventSourcing的DDD项目。目前有许多聚合根,其中许多具有实体集合。更重要的是,一些实体拥有其他实体的集合 问题:出于审核目的读取EventSourcing事件日志 问题:更新/创建/删除实体时,在EventStore中保存事件的最佳方式是什么?记住所有这些:它们必须易于阅读,版本可能不适用于这种情况,但通常粒度事件更可取,域事件可能将用于跨域通信 我是否应该将包含所有实体集合的整个根作为RootChangedEvent保存在根流中 是否应仅将根流中更新/创建/删除的实体

我有一个使用EventSourcing的DDD项目。目前有许多聚合根,其中许多具有实体集合。更重要的是,一些实体拥有其他实体的集合

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

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

  • 我是否应该将包含所有实体集合的整个根作为RootChangedEvent保存在根流中

  • 是否应仅将根流中更新/创建/删除的实体保存为EntityChangedEvent/EntityCreateEvent/EntityRemovedEvent

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

  • 以下是我的项目中的一个示例:

    根管道

    public class Pipeline : AggregateRoot<IPipelineState>
    
    公共类管道:AggregateRoot
    
    它具有实体集合-
    公共IList状态

    每个状态都有实体集合-
    公共IList逻辑


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

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

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

  • 已创建医嘱(医嘱ID=123)
  • OrderItemAdded(orderId=123,“product1”)
  • OrderItemAdded(orderId=123,“product2”)
  • OrderItemRemoved(orderId=123,“product1”)
  • OrderPaid(orderId=123)
  • OrderArchived(orderId=123)
  • 发生这些事件的原因是什么?使用Order,所以Order是您的聚合根,123是它的aggregateId。您甚至可能不需要OrderItems,除非命令处理程序要求这样做(例如,您不希望为已删除的项发出OrderItemRemoved事件)

    对于aggregateRoot 123,您将有一个单一的事件流,并且在您处理PayOrder命令时,没有人可以(比如)添加和订购项

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

    OrderEntityChangedEvent(新状态=付费)表示实体的特定结构
    OrderPaid事件只假设某个地方有一个订单聚合根。

    如果您的事件都是关于CRUD的,这是一个坏消息。通过事件源,如果您的事件是特定于业务的,而不是特定于实体的,您可以灵活地在以后更改域模型。我不确定是否理解您的答案。您不应该保存事件流中有ny个实体。您应该保存事件-您的系统发生了什么?从事件还原到写端的DDD聚合应该包含验证它接收到的命令的最小状态。我无法想象您需要3个级别的实体才能做到这一点。您可以构建任何级别的深层readmodel,但聚合在写端。Maybe示例将有助于理解您的用例。在上面的问题描述中添加了一个示例。