【问题标题】:Domain Events Using DDD/Repo/UoW/Serv [closed]使用 DDD/Repo/UoW/Serv 的域事件 [关闭]
【发布时间】:2019-12-07 18:47:48
【问题描述】:

我正在为工作制作休息服务,使用:

  • EntityFramework 核心。
  • 存储库模式
  • 工作单位。
  • 服务模式。
  • 数据传输对象 (Dto)。
  • 数据访问对象(实体/道)

项目简介:

  • 大型企业 Rest API 服务。

  • 存储库负责 CRUD,并且仅负责 CRUD。

  • UnitOfWork 包含每个存储库,并通过依赖注入获取 DbContext。

  • 我的 Dtos 是贫血模型,我知道很多人认为这是不好的做法,但是当制作一个包含上千个实体的 Master API 时,每个实体包含数百个列,这实际上是必要的。 所以我的 Dto 实际上只是反映了 Dao 的(虽然不是敏感信息)。

  • 每个实体都有自己的存储库。

  • 每个实体都有自己的服务类,主要使用给定实体的存储库。

  • 每个实体都有自己的控制器和服务类,每个控制器都与给定的服务类对话。

  • 服务类只接受Dto,每个函数将Dto转换为Dao,然后验证实体,如果实体无效则抛出异常。调用适当的存储库函数并使用 UnitOfWork 提交函数来保存更改时。

  • 通过导航属性插入、更新和删除被禁用/不允许。

  • 这个数据库在云端,而我工作的公司只使用边缘数据库,所以我们创建了一个“同步引擎”来将数据从旧数据库同步到新的基于云的数据库(这个) .

问题来了,我应该在哪里以及如何实现这些事件?

假设我有一个“用户”实体,它需要一百个字段,并且我在实体内部有一个工厂方法,它需要一百个参数长度,这根本不是最优的,然后就会触发事件甚至在知道它被添加到数据库之前?所以我最终向用户发送了一封电子邮件,但数据库不可用,所以根本没有创建用户。

我知道在 DDD 中你应该设置和聚合并在实体等中包含事件,但是即使写入数据库不成功,事件也会被触发......假设我有一个包含数百个必填字段的模型,在 Dao/Entity 类中有一个工厂方法,它需要一百个参数是不合适的?

提前致谢。 - 真诚地沮丧的人

【问题讨论】:

    标签: c# asp.net rest domain-driven-design repository-pattern


    【解决方案1】:

    沮丧的人,

    通常,您会希望将更改和事件保存在同一个数据库事务中。通过这种方式,您可以保证仅在写入更改时写入您的事件。

    接下来,您应该考虑仅在数据库写入后触发电子邮件警报。考虑一个分布式过程,您从数据库中获取新事件并将它们发布到队列中。然后,您可以使用不同的进程来提取和处理它们(例如,向用户发送电子邮件)。

    一般来说,试图在一个进程中完成所有工作而没有事务保证会导致状态不一致。将您的工作分解为您可以保证的小工作单元,并且不要害怕将工作卸载到队列中,在那里您可以类似地保证工作是否会完成。

    关于你的其他问题,

    • 理想情况下,您应该将根实体包装在聚合中并在那里维护您的逻辑
    • 您应该只有根实体的存储库。他们应该加载任何依赖的子实体。子实体不需要独立加载,因此它们不需要存储库
    • 如果你在处理数百个列,你能不能对这些表和实体进行垂直划分,并将它们变成许多根?也就是说,是否所有列都同时更新/用例?从读取的角度来看,拥有这样大小的实体是低效的,但如果字段是从不同的用例写入的,那么在写入时也是如此,并且在繁重的写入场景下将成为瓶颈。

    希望对您有所帮助。

    【讨论】:

    • 感谢您的回答。将研究分布式过程。所以你的意思是如果我有一个 Order 和 OrderLine 实体,OrderLine 操作应该只能通过 OrderRepository 获得?因为在 Rest Service 中我不允许从子对象插入,所以如果您发送带有 OrderLines 列表的订单,现在不允许这样做
    • 存储库和操作是有区别的。操作处于(域)服务级别。您从存储库加载 Order,然后根据需要修改 OrderLines。然后您将订单保存回来。 Order 有能力在那个时候应用业务逻辑。
    • 如果您将整个订单 DTO 传递回您的服务层,那么您应该从存储库加载该订单,然后根据 DTO 应用您的更改。差异逻辑由您决定。
    • 现在我明白你的意思了,我会尝试组装我的测试项目。非常感谢您,先生,对我帮助很大。
    • 我的荣幸!请随时提出任何后续问题。
    【解决方案2】:

    对域模型的大多数更改都应遵循此顺序

    1. 决定写下什么
    2. 写下来
    3. 告诉全世界您写下的内容

    1happens-before2.

    2happens-before3.

    尝试使 2 和 3 并发打开一个需要解决昂贵问题的世界。所以不要那样做?

    适合某些情况的另一种方法是在将更改写入模型时记下事件(在步骤 2 中),然后使用存储的事件列表来决定广播什么(在步骤 3 中)。

    见 Udi Dahan:Reliable Messaging without Distributed Transactions

    【讨论】:

    • 谢谢先生,真的帮了我大忙!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-23
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多