В чем разница между IQueryable и IEnumerable
Я смущен относительно разницы. Будучи довольно новым для.Net, я знаю, что могу запросить IEnumerables
используя расширения Linq. И что это IQueryable
и чем это отличается?
Смотрите также В чем разница между IQueryable[T] и IEnumerable[T]? что совпадает с этим вопросом.
7 ответов
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).
Увидеть:
В реальной жизни, если вы используете 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.
"Основное отличие состоит в том, что методы расширения, определенные для IQueryable, принимают объекты Expression вместо объектов Func, то есть получаемый им делегат представляет собой дерево выражений, а не метод для вызова. IEnumerable отлично подходит для работы с коллекциями в памяти, но IQueryable позволяет для удаленного источника данных, такого как база данных или веб-служба "
Источник: здесь
IEnumerable IEnumerable лучше всего подходит для работы с коллекцией в памяти. IEnumerable не перемещается между элементами, он только вперед.
IQueryable IQueryable лучше всего подходит для удаленного источника данных, такого как база данных или веб-сервис. IQueryable - это очень мощная функция, которая позволяет использовать различные интересные сценарии отложенного выполнения (например, запросы на основе страниц и композиции).
Поэтому, когда вам нужно просто перебрать коллекцию в памяти, используйте IEnumerable, если вам нужно выполнить какие-либо манипуляции с коллекцией, такой как набор данных и другие источники данных, используйте IQueryable
Принципиальное отличие состоит в том, что IEnumerable будет перечислять все свои элементы все время, в то время как IEqueryable будет перечислять элементы или даже делать другие вещи на основе запроса. Запрос представляет собой выражение (представление данных кода.Net), которое IQueryProvider должен исследовать / интерпретировать / компилировать / как угодно, чтобы генерировать результаты.
Наличие выражения запроса дает два преимущества.
Первое преимущество - это оптимизация. Поскольку такие модификаторы, как "Где", включены в выражение запроса, IQueryProvider может применять невозможные в противном случае оптимизации. Вместо того, чтобы возвращать все элементы, а затем отбрасывать большинство из них из-за предложения "Где", поставщик может использовать хеш-таблицу для поиска элементов с заданным ключом.
Второе преимущество - это гибкость. Поскольку выражения являются структурами данных с возможностью просмотра, вы можете выполнять такие действия, как сериализация запроса и отправлять его на удаленный компьютер (например, linq-to-sql).
IQueriable - это то же самое, что и IEnumerable, но он также предоставляет дополнительные функциональные возможности для реализации пользовательских запросов с Linq. Вот описание на MSDN: http://msdn.microsoft.com/en-us/library/system.linq.iqueryable.aspx
Во-первых, IEnumerable находится в пространстве имен System.Collections, а IQueryable - в пространстве имен System.Linq. Если вы используете IEnumerable при запросе данных из коллекций в памяти, таких как List, Array collection и т. Д. И при запросе данных из коллекций вне памяти (например, удаленная база данных, служба), то вы используете IQueryable. Поскольку при запросе данных из базы данных IEnumerable выполняет запрос на выборку на стороне сервера, загружает данные в память на стороне клиента и затем фильтрует данные. Следовательно делает больше работы и становится медленным. При запросе данных из базы данных IQueryable выполняет запрос выбора на стороне сервера со всеми фильтрами. Следовательно делает меньше работы и становится быстрым.