工作单元模式中的 EF Core 封装
EF Core incapsulation in Unit Of Work pattern
我在加入 DDD 和 EF Core 时遇到问题。
我正在使用 DDD 架构制作项目。作为数据访问级别,我使用取自 here.
的通用工作单元模式
public interface IUnitOfWork
{
IRepository<TDomain> Repository<TDomain>() where TDomain : class;
}
public interface IRepository<TDomain>
{
TDomain Get(Expression<Func<TDomain, bool>> predicate);
}
我使用 EF Core 实现这些接口。
我有一些域模型有 2 类
public class MainClass
{
public int Id { get; set; }
public List<RelatedItem> Items { get; set; }
}
public class RelatedItem
{
public int Id { get; set; }
public MainClass Parent { get; set; }
public DateTime Date { get; set; }
public string SomeProperty { get; set; }
}
在我的项目 MainClass
的现实生活中,收集了数百个 RelatedItems
。为了执行一些操作,我只需要一个 RelatedItem
每个带有某个日期的请求。可以通过搜索 Items
属性.
来完成
在工作单元中封装 EF Core 的性能我必须从 DB 显式加载实体和相关项目,因为业务登录层对 UnitOfWork 存储库的实现一无所知。但是这个操作很慢。
所以我决定创建 MainClassService
注入构造函数 unitOfWork
并且有方法 returns 只有一个 RelatedItem
,并且工作正常。
public class MainClassService
{
IUnitOfWork unitOfWork;
public MainClassService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork ?? throw new ArgumentNullException();
}
public RelatedItem GetRelatedItemByDate(int mainClassId, DateTime date)
{
return unitOfWork.Repository<RelatedItem>().Get(c => c.Parent.Id == mainClassId && c.Date == date);
}
}
所以我有这样的情况,因为 EF Core,我不能直接使用 属性 Items
,但我应该使用它们,因为 DDD 架构。
我的问题是:这样的结构可以吗?
从您的问题看来,MainClass
是聚合根,RelatedItem
是嵌套实体。此设计决策应基于必须保护的业务 rules/invariants。当一个聚合需要变异时,它必须从存储库中完全加载,即聚合根及其所有嵌套实体和值对象必须在内存中才能执行变异命令,无论它有多大
此外,将基础设施服务注入聚合(或嵌套实体)也不是一个好的做法。如果你需要这样做,那么你必须重新考虑你的架构。
因此,从我写的内容中您可以看出,只有当您尝试改变聚合时,问题才会显现出来。如果您只需要阅读或查找它,您可以创建一些专用服务来使用基础结构组件查找数据。您的 MainClassService
似乎就是这种情况,您只需要 read/find 一些 RelatedItem
实体。
为了明确目的只是阅读,MainClassService
需要 return RelatedItem
实体的只读表示。
因此,您刚刚迈出了 CQRS 的第一步,其中模型分为两部分:READ 模型和 WRITE 模型。
我在加入 DDD 和 EF Core 时遇到问题。
我正在使用 DDD 架构制作项目。作为数据访问级别,我使用取自 here.
的通用工作单元模式public interface IUnitOfWork
{
IRepository<TDomain> Repository<TDomain>() where TDomain : class;
}
public interface IRepository<TDomain>
{
TDomain Get(Expression<Func<TDomain, bool>> predicate);
}
我使用 EF Core 实现这些接口。
我有一些域模型有 2 类
public class MainClass
{
public int Id { get; set; }
public List<RelatedItem> Items { get; set; }
}
public class RelatedItem
{
public int Id { get; set; }
public MainClass Parent { get; set; }
public DateTime Date { get; set; }
public string SomeProperty { get; set; }
}
在我的项目 MainClass
的现实生活中,收集了数百个 RelatedItems
。为了执行一些操作,我只需要一个 RelatedItem
每个带有某个日期的请求。可以通过搜索 Items
属性.
在工作单元中封装 EF Core 的性能我必须从 DB 显式加载实体和相关项目,因为业务登录层对 UnitOfWork 存储库的实现一无所知。但是这个操作很慢。
所以我决定创建 MainClassService
注入构造函数 unitOfWork
并且有方法 returns 只有一个 RelatedItem
,并且工作正常。
public class MainClassService
{
IUnitOfWork unitOfWork;
public MainClassService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork ?? throw new ArgumentNullException();
}
public RelatedItem GetRelatedItemByDate(int mainClassId, DateTime date)
{
return unitOfWork.Repository<RelatedItem>().Get(c => c.Parent.Id == mainClassId && c.Date == date);
}
}
所以我有这样的情况,因为 EF Core,我不能直接使用 属性 Items
,但我应该使用它们,因为 DDD 架构。
我的问题是:这样的结构可以吗?
从您的问题看来,MainClass
是聚合根,RelatedItem
是嵌套实体。此设计决策应基于必须保护的业务 rules/invariants。当一个聚合需要变异时,它必须从存储库中完全加载,即聚合根及其所有嵌套实体和值对象必须在内存中才能执行变异命令,无论它有多大
此外,将基础设施服务注入聚合(或嵌套实体)也不是一个好的做法。如果你需要这样做,那么你必须重新考虑你的架构。
因此,从我写的内容中您可以看出,只有当您尝试改变聚合时,问题才会显现出来。如果您只需要阅读或查找它,您可以创建一些专用服务来使用基础结构组件查找数据。您的 MainClassService
似乎就是这种情况,您只需要 read/find 一些 RelatedItem
实体。
为了明确目的只是阅读,MainClassService
需要 return RelatedItem
实体的只读表示。
因此,您刚刚迈出了 CQRS 的第一步,其中模型分为两部分:READ 模型和 WRITE 模型。