使用存储库模式泛型在linq中进行多个连接

时间:2018-03-31 15:48:22

标签: c# entity-framework repository-pattern

我实现了一个存储库模式,其中包含对数据库执行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的新手,这是我使用存储库模式的第一个项目。

2 个答案:

答案 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,以便稍后修改查询。