使用 DDD/Repo/UoW/Serv 的领域事件
Domain Events Using DDD/Repo/UoW/Serv
我正在为工作制作休息服务,使用:
- EntityFramework核心.
- 存储库模式
- 工作单位。
- 服务模式。
- 数据传输对象(Dto)。
- 数据访问对象(Entity/Dao)
项目简介:
大企业休息API服务
存储库只负责 CRUD。
UnitOfWork 包含每个存储库并通过依赖注入获取 DbContext。
我的 Dto 是贫血模型,我知道这被很多人认为是不好的做法,但是当制作一个包含一千个实体的主 API 时,每个实体包含数百列,这实际上是必要的。
所以我的 Dto 实际上只是反映了 Dao 的(虽然不是敏感信息)。
每个实体都有自己的存储库。
每个实体都有自己的服务class,主要使用给定实体的存储库。
每个实体都有自己的控制器和服务 class,每个控制器都与给定的服务对话 class。
服务class只接受Dto,每个函数从Dto转换为Dao,然后验证实体,如果实体不合法则抛出异常。当调用适当的存储库函数并使用 UnitOfWork 提交函数来保存更改时。
允许 disabled/not 通过导航属性插入、更新和删除。
这个数据库在云端,我工作的公司一直只使用边缘数据库,所以我们创建了一个"SyncEngine"来将数据从旧数据库同步到新数据库基于云的(this).
问题来了,我应该在哪里以及如何实施这些事件?
假设我有一个 "User" 实体,它需要一百个字段,我在实体内部有一个工厂方法,它需要一百个参数长度,这根本不是最优的,然后事件会在知道它被添加到数据库之前就被触发了吗?所以我最终向用户发送了一封电子邮件,但是数据库不可用,所以根本没有创建用户。
我知道在 DDD 中你应该设置和聚合并在实体等中包含事件,但是即使写入数据库不成功,事件也会被触发......假设我有一个需要一百个的模型字段,在 Dao/Entity class 中有一个工厂方法是不合适的,它需要一百个参数?
提前致谢。
- 真诚沮丧的人
沮丧的人,
通常,您会希望将更改和事件保存在同一个数据库事务中。通过这种方式,您可以保证您的事件仅在写入您的更改时写入。
接下来,您应该考虑仅在写入数据库后才触发电子邮件警报。考虑一个分布式过程,您可以在其中从数据库中获取新事件并将它们发布到队列中。然后,您可以使用不同的流程来提取和处理它们(例如,向用户发送电子邮件)。
一般来说,尝试在没有事务保证的情况下在一个进程中完成所有工作会导致状态不一致。将您的工作分解成您可以保证的小工作单元,并且不要害怕将工作卸载到队列中,您可以在队列中同样保证工作是否会完成。
关于您的其他问题,
- 理想情况下,您应该将根实体包装在聚合中并在那里维护您的逻辑
- 您应该只有根实体的存储库。他们应该加载任何依赖的子实体。子实体不需要独立加载,因此不需要存储库
- 如果你处理的是上百列,你能不能把这些表和实体垂直分区,变成很多Roots?也就是说,是否所有列都在相同的 time/use 情况下得到更新?从读取的角度来看,拥有这样大小的实体是低效的,但如果字段是从不同的用例写入的,那么在写入时也是如此,并且在大量写入场景下将成为瓶颈。
希望对您有所帮助。
对域模型的大多数更改都应遵循此顺序
- 决定写下什么
- 写下来
- 向全世界讲述您写下的内容
1 happens-before
2.
2 happens-before
3.
尝试让 2 和 3 并发打开了一个需要解决昂贵问题的世界。所以不要那样做?
一种适合某些情况的替代方法是在将更改写入模型时记下事件(在步骤 2 中),然后使用存储的事件列表来决定广播什么(在步骤 3 中) .
我正在为工作制作休息服务,使用:
- EntityFramework核心.
- 存储库模式
- 工作单位。
- 服务模式。
- 数据传输对象(Dto)。
- 数据访问对象(Entity/Dao)
项目简介:
大企业休息API服务
存储库只负责 CRUD。
UnitOfWork 包含每个存储库并通过依赖注入获取 DbContext。
我的 Dto 是贫血模型,我知道这被很多人认为是不好的做法,但是当制作一个包含一千个实体的主 API 时,每个实体包含数百列,这实际上是必要的。 所以我的 Dto 实际上只是反映了 Dao 的(虽然不是敏感信息)。
每个实体都有自己的存储库。
每个实体都有自己的服务class,主要使用给定实体的存储库。
每个实体都有自己的控制器和服务 class,每个控制器都与给定的服务对话 class。
服务class只接受Dto,每个函数从Dto转换为Dao,然后验证实体,如果实体不合法则抛出异常。当调用适当的存储库函数并使用 UnitOfWork 提交函数来保存更改时。
允许 disabled/not 通过导航属性插入、更新和删除。
这个数据库在云端,我工作的公司一直只使用边缘数据库,所以我们创建了一个"SyncEngine"来将数据从旧数据库同步到新数据库基于云的(this).
问题来了,我应该在哪里以及如何实施这些事件?
假设我有一个 "User" 实体,它需要一百个字段,我在实体内部有一个工厂方法,它需要一百个参数长度,这根本不是最优的,然后事件会在知道它被添加到数据库之前就被触发了吗?所以我最终向用户发送了一封电子邮件,但是数据库不可用,所以根本没有创建用户。
我知道在 DDD 中你应该设置和聚合并在实体等中包含事件,但是即使写入数据库不成功,事件也会被触发......假设我有一个需要一百个的模型字段,在 Dao/Entity class 中有一个工厂方法是不合适的,它需要一百个参数?
提前致谢。 - 真诚沮丧的人
沮丧的人,
通常,您会希望将更改和事件保存在同一个数据库事务中。通过这种方式,您可以保证您的事件仅在写入您的更改时写入。
接下来,您应该考虑仅在写入数据库后才触发电子邮件警报。考虑一个分布式过程,您可以在其中从数据库中获取新事件并将它们发布到队列中。然后,您可以使用不同的流程来提取和处理它们(例如,向用户发送电子邮件)。
一般来说,尝试在没有事务保证的情况下在一个进程中完成所有工作会导致状态不一致。将您的工作分解成您可以保证的小工作单元,并且不要害怕将工作卸载到队列中,您可以在队列中同样保证工作是否会完成。
关于您的其他问题,
- 理想情况下,您应该将根实体包装在聚合中并在那里维护您的逻辑
- 您应该只有根实体的存储库。他们应该加载任何依赖的子实体。子实体不需要独立加载,因此不需要存储库
- 如果你处理的是上百列,你能不能把这些表和实体垂直分区,变成很多Roots?也就是说,是否所有列都在相同的 time/use 情况下得到更新?从读取的角度来看,拥有这样大小的实体是低效的,但如果字段是从不同的用例写入的,那么在写入时也是如此,并且在大量写入场景下将成为瓶颈。
希望对您有所帮助。
对域模型的大多数更改都应遵循此顺序
- 决定写下什么
- 写下来
- 向全世界讲述您写下的内容
1 happens-before
2.
2 happens-before
3.
尝试让 2 和 3 并发打开了一个需要解决昂贵问题的世界。所以不要那样做?
一种适合某些情况的替代方法是在将更改写入模型时记下事件(在步骤 2 中),然后使用存储的事件列表来决定广播什么(在步骤 3 中) .