我已经阅读了一些关于通用存储库实现的帖子.我还阅读了一些帖子,解释了从我的存储库中暴露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(我猜的唯一区别是我以通用方式执行此操作).