Ответ 1

Прежде всего, IQueryable<T> расширяет интерфейс IEnumerable<T>, поэтому все, что вы можете сделать с помощью "plain" IEnumerable<T>, вы также можете сделать с IQueryable<T>.

IEnumerable<T> просто имеет метод GetEnumerator(), который возвращает Enumerator<T>, для которого вы можете вызвать его метод MoveNext() для повторения последовательности из T.

Что IQueryable<T> имеет то, что IEnumerable<T> не имеет двух свойств в частности: один, который указывает поставщику запросов (например, провайдер LINQ to SQL), а другой, указывающий на выражение запроса, представляющее объект IQueryable<T> как абстрактное синтаксическое дерево, проходящее через время выполнения, которое может быть понято данным поставщиком запросов (по большей части, вы не можете дать выражение LINQ to SQL Поставщик LINQ to Entities без исключения).

Выражение может просто быть константным выражением самого объекта или более сложного дерева составного набора операторов запросов и операндов. Вызов метода запроса IQueryProvider.Execute() или IQueryProvider.CreateQuery() вызывается с переданным им выражением, а затем возвращается результат запроса или другой IQueryable.

Ответ 2

Основное различие заключается в том, что операторы LINQ для IQueryable<T> принимают Expression объекты вместо делегатов, то есть пользовательская логика запроса, которую он получает, например, предикат или селектор значений, имеет форму дерева выражений вместо делегат метода.

  • IEnumerable<T> отлично подходит для работы с последовательностями, которые повторяются в памяти, но
  • IQueryable<T> позволяет использовать такие объекты памяти, как удаленный источник данных, например, базу данных или веб-службу.

Выполнение запроса:

  • Когда выполнение запроса будет выполняться "в процессе" , обычно все, что требуется, - это код (как код) для выполнения каждой части запроса.

  • Если выполнение будет выполнено вне процесса, логика запроса должна быть представлена ​​в данных, чтобы поставщик LINQ мог преобразовать его в соответствующую форму для вне-памяти - будь то запрос LDAP, SQL или что-то еще.

Больше:

http://www.codeproject.com/KB/cs/646361/WhatHowWhere.jpg

Ответ 3

Это хорошее видео на YouTube, которое демонстрирует, как эти интерфейсы отличаются, стоит посмотреть.

Ниже приводится длинный описательный ответ.

Первым важным моментом, который следует помнить, является IQueryable интерфейс IQueryable наследуется от IEnumerable, поэтому, что бы ни делал IEnumerable, IQueryable также может это делать.

enter image description here

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

Рассмотрим приведенный ниже простой код, который использует IEnumerable со структурой сущностей. Он использует фильтр Where чтобы получить записи, чей EmpId равен 2.

EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees; 
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();

Здесь фильтр выполняется на стороне клиента, где находится код IEnumerable. Другими словами, все данные извлекаются из базы данных, а затем на клиенте сканирует и получает запись с EmpId= 2.

enter image description here

Но теперь посмотрите на приведенный ниже код, мы изменили IEnumerable на IQueryable. Он создает SQL-запрос на стороне сервера, а на стороне клиента отправляются только необходимые данные.

EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp =  emp.Where(x => x.Empid == 2).ToList<Employee>();

enter image description here

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

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

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

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

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

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

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

Ответ 7

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

Ответ 8

Ниже упомянутый небольшой тест может помочь вам понять один аспект различия между IQueryable<T> и IEnumerable<T>. Я воспроизвел этот ответ из этого, где я пытался добавить исправления кому-то другому.

Я создал следующую структуру в БД (DDL script):

CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)

Вот вставка записи script (DML script):

INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO

Теперь моя цель состояла в том, чтобы просто получить первые 2 записи из таблицы Employee в базе данных. Я добавил элемент модели данных сущности ADO.NET в мое консольное приложение, указав на таблицу Employee в моей базе данных и начал писать запросы LINQ.

Код для маршрута IQueryable:

using (var efContext = new EfTestEntities())
{
    IQueryable<int> employees = from e in efContext.Employees  select e.Salary;
    employees = employees.Take(2);

    foreach (var item in employees)
    {
        Console.WriteLine(item);
    }
}

Когда я начал запускать эту программу, я также начал сеанс профилирования SQL Query на моем экземпляре SQL Server и вот сводка о выполнении:

  • Общее количество запущенных запросов: 1
  • Текст запроса: SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]

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

Код для маршрута IEnumerable:

using (var efContext = new EfTestEntities())
{
    IEnumerable<int> employees = from e in efContext.Employees  select e.Salary;
    employees = employees.Take(2);

    foreach (var item in employees)
    {
        Console.WriteLine(item);
    }
}

Сводка выполнения в этом случае:

  • Общее количество запущенных запросов: 1
  • Текст запроса, захваченный в профилировщике SQL: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

Теперь вещь IEnumerable привела все 5 записей, присутствующих в таблице Salary, а затем выполнила фильтрацию в памяти на клиентском компьютере, чтобы получить первые 2 записи. Таким образом, больше данных (3 дополнительных записи в этом случае) было передано по проводам без необходимости.

Ответ 9

Вот что я написал на подобном посту (на эту тему). (И нет, я обычно не цитирую себя, но это очень хорошие статьи.)

"Эта статья полезна: IQueryable vs IEnumerable в LINQ-to-SQL.

Цитата этой статьи: "В соответствии с документацией MSDN вызовы, выполняемые в IQueryable, работают, создавая вместо этого дерево внутреннего выражения." Эти методы, которые расширяют IQueryable (Of T), не выполняют никаких запросов напрямую. Вместо этого их функциональность заключается в создании объекта Expression, который является деревом выражений, представляющим кумулятивный запрос."

Деревья выражений являются очень важной конструкцией в С# и на платформе .NET. (Они важны в целом, но С# делает их очень полезными.) Чтобы лучше понять разницу, я рекомендую прочитать о различиях между выражениями и утверждениями в официальном С# 5.0 здесь. Для продвинутых теоретических концепций, которые входят в лямбда-исчисление, выражения позволяют поддерживать методы как объекты первого класса. Разница между IQueryable и IEnumerable сосредоточена вокруг этой точки. IQueryable строит деревья выражений, тогда как IEnumerable, по крайней мере, не в общих чертах для тех из нас, кто не работает в секретных лабораториях Microsoft.

Вот еще одна очень полезная статья, в которой подробно описываются различия между перспективой push и pull. ( "Push" vs. "pull", я имею в виду направление потока данных. Реактивные методы программирования для .NET и С#

Вот очень хорошая статья, в которой подробно описываются различия между выражением lambdas и выражением lambdas и более подробно обсуждаются понятия выражения tress: Пересмотр делегатов С#, выражение деревья и лямбда-выражения против лямбда-выражений.

Ответ 10

Оба IEnumerable и IQueryable используются для хранения коллекции данных и выполнения операции манипуляции данными, например, для фильтрации данных. Здесь вы можете найти лучшее сравнение различий с примером. http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html введите описание изображения здесь

Ответ 11

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

Найти более подробное разграничение ниже:

IEnumerable

  1. IEnumerable существует в пространстве имен System.Collections
  2. IEnumerable выполняет запрос на выборку на стороне сервера, загружает данные в память на стороне клиента и затем фильтрует данные
  3. IEnumerable подходит для запроса данных из коллекций в памяти, таких как List, Array
  4. IEnumerable полезен для запросов LINQ to Object и LINQ to XML

IQueryable

  1. IQueryable существует в пространстве имен System.Linq
  2. IQueryable выполняет "запрос на выборку" на стороне сервера со всеми фильтрами
  3. IQueryable подходит для запроса данных из коллекций вне памяти (например, удаленная база данных, служба)
  4. IQueryable полезен для запросов LINQ to SQL

Таким образом, IEnumerable обычно используется для обработки коллекций в памяти, тогда как IQueryable обычно используется для манипулирования коллекциями.

Ответ 12

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

Ответ 13

ienumerable: когда мы хотим иметь дело с inprocess-памятью, то есть без привязки данных iqueryable: когда нужно иметь дело с сервером sql, то есть с подключением к данным ilist: операции, такие как добавление объекта, удаление объекта и т.д.