2015-04-13 2 views
2

Я хотел бы знать, должен ли я определять интерфейс, IQueryable over List для групп объектов. Или, возможно, IEnumerable лучше, поскольку типы IEnumerable могут быть переданы в IQueryable для использования с LINQ.Должен ли я указывать IQueryable over List в моих интерфейсах?

Я изучал курс онлайн, и он имел дело с EntityFramework, для которого лучше всего использовать IQueryable, поскольку LINQ использует его (хорошо, что есть больше, чем это, но, вероятно, не важно сейчас). Использовался код ниже, и мне подумалось, следует ли мне указывать IQueryable вместо List для моих групп объектов.

namespace eManager.Domain 
{ 
    public interface IDepartmentDataSource 
    { 
     IQueryable<Employee> Employees { get; } 
     IQueryable<Department> Departments { get; } 
    } 

Если бы я строил интерфейс для сервиса, который вызывает хранилище, чтобы получить сотрудников, я обычно указывают

List <Employees> 

, но это лучшая практика? Является ли IQueryable большей гибкостью для классов, реализующих мой интерфейс? Что делать с накладными расходами на импорт LINQ, если они им не нужны (скажем, они хотят только List)? Должен ли я использовать IEnumerable по обоим из них?

+2

Возможно, вы должны пометить свой вопрос «C#», чтобы привлечь больше внимания. – Robert

+0

О, LINQ фактически использует 'IEnumerable' так же легко. Разница заключается в том, хотите ли вы предоставить набор данных, с которыми может работать вызывающий, или прокси-сервер для этих данных. Лично я бы пошел с 'IEnumerable' /' IList', если у вас нет конкретной причины использовать 'IQueryable'. 'IQueryable' делает ваш интерфейс waaaay слишком широким. Сделайте свой интерфейс более жестким, чем «вот все сотрудники, делайте с ними все, что хотите» :) – Luaan

+0

С 'IQueryable' вы возлагаете бремя на разработчика интерфейса. Наложение бремени имеет смысл только в том случае, если есть код, требующий этого интерфейса. Есть ли код, который кричит «Мне действительно нужно« IQueryable »прямо здесь»? – Dialecticus

ответ

2

Интерфейс IQueryable представляет собой запрос на Entity Framework, который еще не выполнен. Когда вы вызываете ToList(), First() или FirstOrDefault() и т. Д. На IQueryable Entity Framework построит SQL-запрос и запросит базу данных.

IEnumerable С другой стороны, это «просто» перечислитель на коллекции. Вы можете использовать его для фильтрации коллекции, но вы должны использовать LINQ to Objects. Entity Framework не вступает в игру здесь.

Чтобы ответить на ваш вопрос: это зависит. Если вы хотите, чтобы клиенты вашего репозитория могли дополнительно настроить запросы, которые они могут выполнить, вы должны выставить IQueryable, но если вы хотите, чтобы полный контроль в вашем репозитории о том, как запрашивается база данных, вы можете использовать IEnumerable.

Я предпочитаю использовать IEnumerable, потому что это не утечка использования Entity Framework во всем приложении. Репозиторий отвечает за доступ к базе данных. Также проще сделать LINQ для оптимизации EF, потому что запросы находятся только в репозитории.

+1

http://programmers.stackexchange.com/a/220126/75584 – Guillaume

+0

Из того, что вы сказали, я чувствую, что репозиторий должен использовать IQueryable, чтобы он мог выполнять запросы с LINQ. Служба, которая его вызывает, должна вернуть своим клиентам IEnumerable. Служба должна сказать своему клиенту: «Вы спросили меня об этих данных, вот он, я сделан». Любая дополнительная фильтрация должна выполняться клиентом - услуге все равно. – VictorySaber

+0

Да, репозиторий неявно использует IQueryable, потому что это то, что предоставляет Entity Framework. Когда вы возвращаете коллекцию элементов из репозитория, вы можете вернуть IEnumerable из репозитория. Чтобы убедиться, что вы не открываете IQueryable из репозитория, вы должны вызывать ToList() в IQueryable, чтобы SQL-запрос выполнялся. –

2

Что я обычно делаю, это сделать репозитории возвращенными IQueryable. Затем в BL укажите либо IEnumerable, либо IQueryble. Важно знать основные различия между IQueryble и IEnumerable.

Допустим, вы запрашиваете данные в IEnumerable IEnumerable employees=this.repository.GetAll(); Теперь, скажем, эта конкретная функция требует только сотрудников с возрастом более 21, а остальные не нужны.

Вы бы сделали: employees.Where(a=>a.Age>21) В этом случае исходный запрос будет загружен в память, а затем будет использоваться приложение Where.

Теперь предположим, вы изменить функцию для извлечения данных в IQueryable IQueryable employees=this.repository.GetAll(); employees.Where(a=>a.Age>21) На этот раз при изменении запроса с ИНЕКЕ, весь запрос будет выполнен в базе данных (если это возможно), и вы будете только получить сотрудников с возрастом старше 21 года из базы данных.

В случае IEnumerable вы получите всех сотрудников из базы данных, а затем они будут отфильтрованы в памяти, чтобы удовлетворить условия условия.

Использовать IEnumerable, IList или что-то еще? Если вы знаете, какие операции будут выполняться в коллекции, вы можете легко выбрать, какой интерфейс использовать. В принципе, если вы будете только перебирать коллекцию, вы должны использовать IEnumerable. Если вы сделаете больше операций, вам нужно выбрать соответствующий интерфейс. Есть хорошие видео коллекции .NET в множественном числе.