我实现了一个存储库模式,其中包含对数据库执行CRUD操作的通用方法列表。这说明如下。
public Repository(DbContext context)
{
_entities = context;
_dbset = context.Set<T>();
}
public IEnmerable<T> GetAll()
{
return _dbset.AsEnumerable<T>();
}
接下来,我有一个实现上述存储库类的服务层。
TruckService
在这个类中,为了使用存储库泛型方法,我有以下代码:
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的新手,这是我使用存储库模式的第一个项目。
答案 0 :(得分:1)
返回数据库中所有实体的IEnumerable集合是一种完美的方式来射击自己。避免这样做,因为它会将所有数据加载到内存中。
你可以使用IQueryable,不像IEnumerable,它在数据库中执行查询,你可以添加过滤,它实际上不会执行查询并加载结果,直到你实现(如调用ToList(),FirstOrDefault()和其他几个)。
外键,导航属性是可以用来轻松地在实体之间导航的所有工具,并为自己节省了大量的显式连接。您可以使用诸如预期加载的内容来获得您希望经常使用的导航属性。 EF的主要目标之一是帮助您编写更少的代码。它可以节省你很多时间,也可以减少你错误的地方(更少的代码,更少的错误,但在使用它时仍然要小心)。
无论您是否要使用存储库模式,都是您的选择。有些人认为这是对EF上下文和集合已经提供的抽象的不必要的抽象。有些人认为将业务逻辑与数据库访问分开是必要的。但是,在使用之前阅读很多内容非常重要,特别是如果您是EF的新手。以下是他们文档中的Microsoft give as an example。
答案 1 :(得分:0)
我建议您从通用存储库返回IQueryable<T>
,以便稍后可以在特定的继承存储库中修改查询。
但是,为了在通用存储库中使用Include
,您可以传递给包含属性的GetAll方法params Func<T, object>[]
,然后将其聚合到查询中。
请参阅this gist.
但是,您无法使用ThenInclude
。考虑返回IQueryable
,以便稍后修改查询。