【发布时间】:2018-09-10 09:21:42
【问题描述】:
我已经实现了一个存储库模式,其中包含对数据库执行 CRUD 操作的通用方法列表。如下图所示。
public Repository(DbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public IEnmerable<T> GetAll()
{
return _dbset.AsEnumerable<T>();
}
接下来,我有一个实现上述存储库类的 service 层。
卡车服务
在这个类中,为了使用存储库通用方法,我有以下代码:
private IRepository<Workers> _repositoryWorkers;
private IRepository<Jobs> _repositoryJobs;
private IRepository<Depts> _repositoryDepts;
public WorkerService(IRepository<Workers> repositoryWorkers, IRepository<Jobs> repositoryJobs, IRepository<Depts> repositoryDepts)
{
_repositoryWorkers = repositoryWorkers;
_repositoryJobs = repositoryJobs;
_repositoryDepts = repositoryDepts
}
// a query that makes multiple joins to retrieve data.
from h in _repositoryWorkers.GetAll()
join p in _repositoryJobs.GetAll() on h.Id equals p.Id
join q in _repositoryDepts.GetAll() on h.Id equals q.Id
所以,在上面的TruckService类中,我实现了IRepository接口来继承泛型方法。在本课程中,我正在执行一个查询,该查询执行多个连接以从数据库中获取数据。我正确获取了所有数据,但我在某处读到这种方法是:
混合和匹配基于存储库的查询和 LINQ 查询。相当 与真正的联接相比,您正在获取每个表的所有行 然后在内存中加入它们
那么,在这种情况下,有人可以告诉我一个更好/更有效的方法来进行多重连接吗?
*请注意,我是 EF 新手,这是我第一个使用存储库模式的项目。
【问题讨论】:
-
存储库上的特殊方法。例如
GetJobsByWorkerId -
_repositoryJobs.GetAll() on h.Id equals p.Id您正在有效地下载整个表,只是为了进行内存查询。专业提示:当您刚刚学习实体框架时,不要遵循存储库模式。存储库模式可能适用于某些用例,但不适用于 EF。作为一个额外的评论:每当你在使用实体框架时看到IEnumerable<T>,你就做错了 -
我的建议:删除任何与存储库相关的内容并直接使用 EF,简单明了
-
短期内 - 不要使用存储库反模式。使用
DbContext和 EF 模型的全部功能,尤其是导航属性、预加载、投影查询等。 -
创建一个我的 DbContext 实例并使用该对象通过连接查询我的表 几乎。但现在不使用连接,而是使用导航属性。存储库是一种反模式,因为 1) 通常它只是一个围绕
DbSet的薄(= 无用)包装器,2) 它阻碍 LINQ 查询组合,以及 3) 它引入了模棱两可的职责(“哪个存储库负责我的嵌套实体?”)。
标签: c# entity-framework repository-pattern