Я прочитал несколько сообщений о реализации универсального репозитория. Я также прочитал ряд сообщений, объясняющих разницу между предоставлением 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>
. В методе My find я возвращаю объект IQueryable<T>
, но клиент видит его только как IEnumerable<T>
. Означает ли это, что если я буду выполнять какие-либо последующие запросы к объекту IEnumerable<T>
, он фактически выполнит операции с базой данных и вернет только результаты (потому что объект являетсяIQueryable
в данном случае )? Или,Where
, переданное в метод Find
, выполняется в базе данных, а все последующие запросы, выполняемые на объекте IEnumerable<T>
, выполняются на клиенте. Или,IEnumarable<T>
, IQueryable<T>
и Linq
.Обновление:
На самом деле я довольно удивлен ответами, которые я получил в комментариях. Мой первоначальный репозиторий вернул IQueryable, и последующие исследования привели меня к мысли, что это нехорошо (, например.если мой viewModel принимает репозиторий в своем конструкторе, он может вызывать любой запрос, который захочет, что затрудняет тестирование ).
Все решения, которые я видел для этого до сих пор, включают создание репозиториев для конкретных объектов, чтобы IQueryable не был доступен (. Единственная разница, которую я полагаю, заключается в том, что я делаю это общим способом ).