在通用存储库中使用IEnumerable <T>和IQueryable <T>

我已经阅读了一些关于实施通用知识库的文章。 我还阅读了一些解释从我的存储库中暴露IEnumerable与IQueryable之间的区别的帖子。

我希望能够灵活地在数据库中过滤数据(而不是客户端的内存),但希望避免为我的所有实体(以及实现这些接口的具体类)定义单独的存储库接口。

到目前为止,我的仓库看起来像这样

public interface IRepository<T>
{
    IEnumerable<T> GetAll();
    IEnumerable<T> Find(Expression<Func<T, bool>> where);

    void Add(T entity);
    void Attach(T entity);
    void Delete(T entity);
}

一个具体实现的例子是:

public class Repository<T> : IRepository<T> where T : class
{
    private DbContext _context;
    private DbSet<T> _entitySet;

    public Repository(DbContext context)
    {
        _context = context;
        _entitySet = _context.Set<T>();
    }

    public IEnumerable<T> GetAll()
    {
        return _entitySet;
    }

    public IEnumerable<T> Find(Expression<Func<T, bool>> where)
    {
        return _entitySet.Where(where);
    }

    public void Add(T entity)
    {
        _entitySet.Add(entity);
    }

    public void Attach(T entity)
    {
        _entitySet.Attach(entity);
    }

    public void Delete(T entity)
    {
        _entitySet.Remove(entity);
    }
}

在这种情况下,我的存储库使用DbContext所以我想知道的是它如何与通用接口一起工作:

  • IQueryable<T>IEnumerable<T>派生。 在我的find方法中,我返回一个IQueryable<T>对象,但客户端仅将其视为IEnumerable<T> 。 这是否意味着如果我对IEnumerable<T>对象执行任何后续查询,它实际上将对数据库执行操作并仅返回结果(因为在这种情况下对象是IQueryable )? 要么,
  • 只有传递给Find方法的Where子句在数据库上执行,并且在IEnumerable<T>对象上执行的任何后续查询都将在客户端上执行。 要么,
  • 这些都不会发生,我完全误解了IEnumarable<T>IQueryable<T>Linq工作原理。
  • 更新:

    对于我在评论中收到的答复,我感到非常惊讶。 我的原始库返回IQueryable,随后的研究让我相信这是一件坏事(例如,如果我的viewModel在其构造函数中接受了一个存储库,它可以调用它想要的任何查询,这使得它更难测试)。

    到目前为止,我所见过的所有解决方案都涉及到创建特定于实体的存储库,以便IQueryable不被公开(我唯一的区别是我以通用方式进行此操作)。


    因为您正在返回IEnumerable<T>所有后续调用将在内存中完成(本地)。

    有一点需要记住的是,LINQ使用一组扩展方法进行操作。 IQueryable<T>有扩展方法,它支持在本地以外的位置执行查询所需的所有必要连线,以及仅用于本地工作的IEnumerable<T>扩展方法。

    请注意,选择哪些是基于编译时类型,而不是运行时类型。 因此,投射到IEnumerableIQueryable将被视为IEnumerable 。 这与类通常的工作方式不同(多亏了多态性),但它允许呼叫站点控制如何执行这些操作。

    一个有用的例子是,当你需要获得表中的所有记录,然后对它们进行计数。 无论如何你都要获得所有结果,不需要在SQL中执行计数。

    链接地址: http://www.djcxy.com/p/62097.html

    上一篇: Using IEnumerable<T> and IQueryable<T> in a generic repository

    下一篇: ends with (suffix) and contains string search using MATCH in SQLite FTS