DDD聚合在 ASP.NET Core中的实现

目录

工作单元(UnitOfWork)的实现

聚合与聚合根的实现

实现

聚合与DbContext的关系

区分聚合根实体和其他实体

跨表查询

实现实体不要面向数据库建模


工作单元(UnitOfWork)的实现

  1. EFCore的DbContext:跟踪对象状态的改变;SaveChanges把所有的改变一次性地提交到数据库中,是一个事务。因此DbContext是天然的UnitOfWork实现。
  2. 需要把DbContext再封装一次UoW吗?两种观点。
    观点一:可以以后有切换其他ORM的可能,所以把DBContext封装起来。
    观点二:不需要封装,直接用DBContext就行。

聚合与聚合根的实现

  1. 即使一个实体类型没有声明对应的DbSet类型的属性,只要EF Core遇到实体对象,EF Core仍然会像对待其他实体对象一样处理。
  2. 因此我们可以在上下文中只为聚合根实体声明DbSet类型的属性。对非聚合根实体、值对象的操作都通过根实体进行。
  3. 跨聚合只能引用根实体的Id,而不是根实体对象。

实现

  1. 聚合根实体中定义对聚合内的所有实体进行操作的方法。
  2. 只在DBContext中为聚合根定义DbSet属性。

聚合与DbContext的关系

如果一个微服务中有多个聚合根,那么是每个聚合根的实体放到一个单独的上下文中,还是把所有实体放到同一个上下文中?各自的优缺点是什么?

  1. 单独上下文:每个聚合有自己的DBContext,隔离性更好
  2. 同一个上下文:它们之间的关系仍然比它们和其他微服务中的实体关系更紧密,而且我们还会在应用服务中进行跨聚合的组合操作。进行联合查询的时候可以获得更好的性能,也能更容易实现强一致性的事务。 

区分聚合根实体和其他实体

定义一个不包含任何成员的标识接口,比如IAggregateRoot,然后要求所有的聚合根实体类都实现这个接口。

跨表查询

  1. 所有跨聚合的数据查询都应该是通过领域服务的协作来完成的,而不应该是直接在数据库表之间进行join查询。会有性能损失,需要做权衡,不是死规矩。
  2. 对于统计、汇总等报表类的应用,则不需要遵循聚合的约束,可以通过执行原生SQL等方式进行跨表的查询。
  3. 跨聚合进行实体引用,只能引用根实体,并且只能引用根实体的Id,而不是根实体对象。
  4. 每个微服务管理自己的数据库,有可能两个微服务用的是两个数据库。

实现实体不要面向数据库建模

建模的时候不要先考虑实体在数据库中如何保存。比如实体类和数据表具有直接的对应关系,实体类中属性和数据表中的列几乎完全一致。这样设计出来的类称不上“实体类”,只能被成为数据对象(Data Object)。更不要用DB First(反向工程)。

应该不考虑数据库实现的情况下进行领域模型建模,然后再使用Fluent API等对实体类和数据库之间做适配。在实现的时候,可能需要对建模进行妥协性修改,但是这不应该在最开始被考虑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值