Использование 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, поэтому я хотел бы знать, как это работает с универсальным интерфейсом :

  1. IQueryable<T>. вытекает из IEnumerable<T>. В методе My find я возвращаю объект IQueryable<T>, но клиент видит его только как IEnumerable<T>. Означает ли это, что если я буду выполнять какие-либо последующие запросы к объекту IEnumerable<T>, он фактически выполнит операции с базой данных и вернет только результаты (потому что объект являетсяIQueryableв данном случае )? Или,
  2. Только предложение Where, переданное в метод Find, выполняется в базе данных, а все последующие запросы, выполняемые на объекте IEnumerable<T>, выполняются на клиенте. Или,
  3. Ничего из этого не происходит, и я совершенно неправильно понял, как работают IEnumarable<T>, IQueryable<T>и Linq.

Обновление:

На самом деле я довольно удивлен ответами, которые я получил в комментариях. Мой первоначальный репозиторий вернул IQueryable, и последующие исследования привели меня к мысли, что это нехорошо (, например.если мой viewModel принимает репозиторий в своем конструкторе, он может вызывать любой запрос, который захочет, что затрудняет тестирование ).

Все решения, которые я видел для этого до сих пор, включают создание репозиториев для конкретных объектов, чтобы IQueryable не был доступен (. Единственная разница, которую я полагаю, заключается в том, что я делаю это общим способом ).

8
задан Benjamin Gale 1 August 2012 в 08:00
поделиться