В чем разница между IQueryable и IEnumerable - PullRequest
145 голосов
/ 12 марта 2010

Я запутался в разнице. Будучи довольно новым для .Net, я знаю, что могу запросить IEnumerables, используя расширения Linq. Так что же это за IQueryable и чем оно отличается?


См. Также В чем разница между IQueryable [T] и IEnumerable [T]? , который совпадает с этим вопросом.

Ответы [ 7 ]

183 голосов
/ 12 марта 2010

IEnumerable<T> представляет курсор только вперед T. В .NET 3.5 добавлены методы расширения, включающие LINQ standard query operators, такие как Where и First, причем любые операторы, которым требуются предикаты или анонимные функции, принимают Func<T>.

IQueryable<T> реализует те же стандартные операторы запросов LINQ, но принимает Expression<Func<T>> для предикатов и анонимных функций. Expression<T> - это скомпилированное дерево выражений, разбитая версия метода («наполовину скомпилированный», если хотите), который может быть проанализирован поставщиком запрашиваемого и использован соответствующим образом.

Например:

IEnumerable<Person> people = GetEnumerablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

IQueryable<Person> people = GetQueryablePeople();
Person person = people.Where(x => x.Age > 18).FirstOrDefault();

В первом блоке x => x.Age > 18 - это анонимный метод (Func<Person, bool>), который может быть выполнен как любой другой метод. Enumerable.Where будет выполнять метод один раз для каждого человека, yield значений, для которых метод вернул true.

Во втором блоке x => x.Age > 18 - это дерево выражений (Expression<Func<Person, bool>>), которое можно рассматривать как «свойство« Возраст »> 18».

Это позволяет существовать таким вещам, как LINQ-to-SQL, поскольку они могут анализировать дерево выражений и преобразовывать его в эквивалентный SQL. А поскольку провайдеру не нужно выполнять до перечисления IQueryable (в конце концов, он реализует IEnumerable<T>), он может объединить несколько операторов запросов (в приведенном выше примере Where и FirstOrDefault), чтобы сделать их более умными выбор способа выполнения всего запроса к базовому источнику данных (например, использование SELECT TOP 1 в SQL).

См:

78 голосов
/ 12 марта 2010

В реальной жизни, если вы используете ORM, такой как LINQ-to-SQL

  • Если вы создаете IQueryable, тогда запрос может быть преобразован в sql и запущен на сервере базы данных
  • Если вы создадите IEnumerable, то все строки будут извлечены в память как объекты перед выполнением запроса.

В обоих случаях, если вы не вызовете ToList() или ToArray(), запрос будет выполняться каждый раз, когда он используется, так что, скажем, у вас есть IQueryable, и вы заполняете 4 списка из него, тогда запрос будет выполнен к базе данных 4 раза.

Также, если вы расширите свой запрос:

q.Select(x.name = "a").ToList()

Тогда с IQueryable сгенерированный SQL будет содержать where name = "a", но с IEnumerable из базы данных будет извлечено гораздо больше ролей, затем проверка x.name = "a" будет выполнена .NET.

35 голосов
/ 12 марта 2010

"Основное отличие состоит в том, что методы расширения, определенные для IQueryable, принимают объекты Expression вместо объектов Func, то есть получаемый им делегат представляет собой дерево выражений, а не метод для вызова. IEnumerable отлично подходит для работы с коллекциями в памяти, но IQueryable допускает удаленный источник данных, такой как база данных или веб-служба "

Источник: здесь

17 голосов
/ 10 мая 2012

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

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

Поэтому, когда вам нужно просто выполнить итерацию по коллекции в памяти, используйте IEnumerable, если вам нужно выполнить какие-либо манипуляции с коллекцией, такой как набор данных и другие источники данных, используйте IQueryable

9 голосов
/ 12 марта 2010

Принципиальное отличие состоит в том, что IEnumerable будет перечислять все свои элементы все время, в то время как IEqueryable будет перечислять элементы или даже выполнять другие действия на основе запроса. Запрос представляет собой выражение (представление данных кода .Net), которое IQueryProvider должен исследовать / интерпретировать / компилировать / как угодно, чтобы генерировать результаты.

Наличие выражения запроса дает два преимущества.

Первое преимущество - оптимизация. Поскольку такие модификаторы, как «Где», включены в выражение запроса, IQueryProvider может применять иначе невозможные оптимизации. Вместо того, чтобы возвращать все элементы, а затем отбрасывать большинство из них из-за предложения «Где», поставщик может использовать хеш-таблицу для поиска элементов с данным ключом.

Вторым преимуществом является гибкость. Поскольку выражения являются структурами данных с возможностью просмотра, вы можете выполнять сериализацию запроса и отправлять его на удаленный компьютер (например, linq-to-sql).

1 голос
/ 12 июня 2014

Во-первых, IEnumerable находится в пространстве имен System.Collections, а IQueryable - в пространстве имен System.Linq. Если вы используете IEnumerable при запросе данных из коллекций в памяти, таких как List, Array collection и т. Д. И при запросе данных из коллекций вне памяти (например, удаленная база данных, служба), то вы используете IQueryable. Поскольку при запросе данных из базы данных IEnumerable выполняет запрос на выборку на стороне сервера, загружает данные в память на стороне клиента и затем фильтрует данные. Следовательно делает больше работы и становится медленным. При запросе данных из базы данных IQueryable выполняет запрос выбора на стороне сервера со всеми фильтрами. Следовательно делает меньше работы и становится быстрым.

1 голос
/ 12 марта 2010

IQueriable - это то же самое, что и IEnumerable, но он также предоставляет дополнительные функциональные возможности для реализации пользовательских запросов с Linq. Вот описание на MSDN: http://msdn.microsoft.com/en-us/library/system.linq.iqueryable.aspx

...