В чем разница между 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> - это скомпилированное дерево выражений, разбитая версия метода ("наполовину скомпилированная", если хотите), которая может быть анализируется поставщиком queryable и используется соответственно.

например:

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 выполнит метод один раз для каждого человека,yielding значения, для которых метод вернул true.

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

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


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

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


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

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

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


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

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

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

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


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


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