C# 使用DDD/Repo/UoW/Serv的域事件

C# 使用DDD/Repo/UoW/Serv的域事件,c#,asp.net,rest,domain-driven-design,repository-pattern,C#,Asp.net,Rest,Domain Driven Design,Repository Pattern,我正在为工作提供休息服务,使用: 实体框架核心 存储库模式 工作单位 服务模式 数据传输对象(Dto) 数据访问对象(实体/Dao) 项目简介: 大型企业RESTAPI服务 存储库负责CRUD,并且只负责CRUD UnitOfWork包含每个存储库,并通过依赖项注入获取DbContext 我的DTO是贫乏的模型,我知道这被很多人认为是不好的做法,但当制作一个包含上百列的1000个实体的主API时,这实际上是必要的。 所以我的Dto实际上只是反映了Dao的(虽然不是敏感信息) 每个实体都有自

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

  • 实体框架核心
  • 存储库模式
  • 工作单位
  • 服务模式
  • 数据传输对象(Dto)
  • 数据访问对象(实体/Dao)
项目简介:

  • 大型企业RESTAPI服务

  • 存储库负责CRUD,并且只负责CRUD

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

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

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

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

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

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

  • 已禁用/不允许按导航属性插入、更新和删除

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

问题来了,我应该在哪里以及如何实施这些活动?

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

我知道在DDD中,您应该设置并聚合实体中的事件等,但是即使写入DB失败,事件也会被触发。。。假设我有一个有一百个必填字段的模型,在Dao/Entity类中有一个工厂方法是不合适的,它需要一百个参数

提前谢谢。 -真诚失意的人

失意的人

通常,您希望在同一数据库事务中保存更改和事件。这样,您可以保证只有在写入更改时才写入事件

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

一般来说,试图在一个进程中完成所有工作而不提供事务性保证会导致状态不一致。把你的工作分成你可以保证的小部分,不要害怕把工作转移到队列中,在队列中你同样可以保证工作是否会完成

关于你的其他问题,

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

希望有帮助

对域模型的大多数更改应遵循以下顺序

  • 决定写什么
  • 写下来
  • 告诉全世界你写下了什么
  • 1
    发生在
    2之前

    2
    发生在
    3之前

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

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


    见Udi Dahan:。

    谢谢您的回答。我们将研究分布式流程。你的意思是如果我有一个订单和订单行实体,订单行操作应该只能通过OrderRepository使用?因为在Rest服务中,我不允许从子对象插入,所以如果您以带有医嘱行列表的顺序发送,这是目前不允许的,存储库和操作之间存在差异。操作处于(域)服务级别。从存储库加载订单,然后根据需要修改订单行。然后你把订单存回去。订单当时可以应用业务逻辑。如果要将整个订单DTO传递回服务层,则应从存储库加载该订单,然后根据DTO应用更改。差异逻辑取决于您。现在我明白您的意思了,我将尝试组装我的测试项目。非常感谢你,先生,帮了我很多。我的荣幸!请随时提出任何后续问题。谢谢您,先生,真的帮助了我!