c# – 在通用存储库中使用IEnumerable和IQueryable

前端之家收集整理的这篇文章主要介绍了c# – 在通用存储库中使用IEnumerable和IQueryable前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经阅读了一些关于通用存储库实现的帖子.我还阅读了一些帖子,解释了从我的存储库中暴露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>.在我的查找方法中,我将返回IQueryable< T>对象,但客户端只将其视为IEnumerable< T>.这是否意味着如果我在IEnumerable< T>上执行任何后续查询对象它将实际执行数据库上的操作并仅返回结果(因为在这种情况下对象是IQueryable)?要么,
>仅对数据库执行传递给Find方法的Where子句以及对IEnumerable< T>执行的任何后续查询.对象在客户端上执行.要么,
>这些都没有发生,我完全误解了IEnumarable< T>,IQueryable< T>和林克的作品.

更新:

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

到目前为止,我所看到的所有解决方案都涉及创建特定于实体的存储库,以便不暴露IQueryable(我猜的唯一区别是我以通用方式执行此操作).

@H_403_25@解决方法
因为你要返回IEnumerable< T>所有后续调用都将在内存中完成(本地).

要记住的一件事是LINQ使用一组扩展方法. IQueryable< T>有扩展方法.其支持在本地以外的位置执行查询的所有必要布线,以及IEnumerable< T>的扩展方法.只是在本地工作.

请注意,选择了哪一个基于编译时类型,而不是运行时类型.因此,强制转换为IEnumerable的IQueryable将被视为IEnumerable.这与类通常工作的方式不同(多亏了多态)但是它允许调用站点控制如何执行这些操作.

这有用的一个示例是当您需要获取表中的所有记录然后对它们进行计数时.如果要获得所有结果,则无需在sql中执行计数.

猜你在找的C#相关文章