В чем разница между IQueryable<T>
и IEnumerable<T>
?
См. также Какая разница между IQueryable и IEnumerable, которая накладывается на этот вопрос.
В чем разница между IQueryable<T>
и IEnumerable<T>
?
См. также Какая разница между IQueryable и IEnumerable, которая накладывается на этот вопрос.
Прежде всего, 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
.
Основное различие заключается в том, что операторы LINQ для IQueryable<T>
принимают Expression
объекты вместо делегатов, то есть пользовательская логика запроса, которую он получает, например, предикат или селектор значений, имеет форму дерева выражений вместо делегат метода.
IEnumerable<T>
отлично подходит для работы с последовательностями, которые повторяются в памяти, ноIQueryable<T>
позволяет использовать такие объекты памяти, как удаленный источник данных, например, базу данных или веб-службу.Когда выполнение запроса будет выполняться "в процессе" , обычно все, что требуется, - это код (как код) для выполнения каждой части запроса.
Если выполнение будет выполнено вне процесса, логика запроса должна быть представлена в данных, чтобы поставщик LINQ мог преобразовать его в соответствующую форму для вне-памяти - будь то запрос LDAP, SQL или что-то еще.
Больше:
IEnumerable<T>
и IQueryable<T>
IEnumerable<T>
vs IQueryable<T>
" IEnumerable
, IQueryable
, IObservable
и IQbservable
Это хорошее видео на YouTube, которое демонстрирует, как эти интерфейсы отличаются, стоит посмотреть.
Ниже приводится длинный описательный ответ.
Первым важным моментом, который следует помнить, является IQueryable
интерфейс IQueryable
наследуется от IEnumerable
, поэтому, что бы ни делал IEnumerable
, IQueryable
также может это делать.
Есть много различий, но давайте поговорим об одной большой разнице, которая имеет самое большое значение. Интерфейс 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
.
Но теперь посмотрите на приведенный ниже код, мы изменили IEnumerable
на IQueryable
. Он создает SQL-запрос на стороне сервера, а на стороне клиента отправляются только необходимые данные.
EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();
Таким образом, разница между IQueryable
и IEnumerable
заключается в том, где выполняется логика фильтра. Один выполняется на стороне клиента, а другой - в базе данных.
Поэтому, если вы работаете только со сбором данных в памяти, IEnumerable
является хорошим выбором, но если вы хотите запросить сбор данных, который связан с базой данных, IQueryable - лучший выбор, поскольку он уменьшает сетевой трафик и использует возможности языка SQL.
IEnumerable IEnumerable лучше всего подходит для работы с коллекцией памяти (или локальными запросами). IEnumerable не перемещается между элементами, это только передовая коллекция.
IQueryable: IQueryable наилучшим образом подходит для удаленного источника данных, например, базы данных или веб-службы (или удаленных запросов). IQueryable - это очень мощная функция, которая позволяет использовать множество интересных сценариев отложенного исполнения (например, запросы подкачки и композиции).
Поэтому, когда вам нужно просто перебирать коллекцию в памяти, используйте IEnumerable, если вам нужно делать какие-либо манипуляции с коллекцией, например, с помощью набора данных и других источников данных, используйте IQueryable
Другими существенными отличиями является то, что IEnumerable выполняет запрос выбора на стороне сервера, загружает данные в памяти на стороне клиента, а затем фильтрует данные, а IQueryable выполняет запрос выбора на стороне сервера со всеми фильтрами.
В реальной жизни, если вы используете ORM, например LINQ-to-SQL
В обоих случаях, если вы не вызываете ToList()
или ToArray()
, тогда запрос будет выполняться каждый раз, когда он будет использован, так что, скажем, у вас есть IQueryable<T>
и вы заполните 4 списка из него, то запрос будет выполняться в базе данных 4 раза.
Также, если вы предоставите запрос:
q.Where(x.name = "a").ToList()
Затем с помощью IQueryable сгенерированный SQL будет содержать "где name =" a ", но с IEnumerable будет выведено еще много ролей из базы данных, тогда проверка x.name =" a "будет выполнена. NET.
IEnumerable ссылается на коллекцию, но IQueryable - это просто запрос, и он будет сгенерирован внутри дерева выражений. Мы будем запускать этот запрос для получения данных из базы данных.
Ниже упомянутый небольшой тест может помочь вам понять один аспект различия между 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 и вот сводка о выполнении:
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);
}
}
Сводка выполнения в этом случае:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]
Теперь вещь IEnumerable
привела все 5 записей, присутствующих в таблице Salary
, а затем выполнила фильтрацию в памяти на клиентском компьютере, чтобы получить первые 2 записи. Таким образом, больше данных (3 дополнительных записи в этом случае) было передано по проводам без необходимости.
Вот что я написал на подобном посту (на эту тему). (И нет, я обычно не цитирую себя, но это очень хорошие статьи.)
"Эта статья полезна: 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: Пересмотр делегатов С#, выражение деревья и лямбда-выражения против лямбда-выражений.
Оба IEnumerable и IQueryable используются для хранения коллекции данных и выполнения операции манипуляции данными, например, для фильтрации данных. Здесь вы можете найти лучшее сравнение различий с примером. http://www.gurujipoint.com/2017/05/difference-between-ienumerable-and.html
Мы используем IEnumerable
и IQueryable
для манипулирования данными, полученными из базы данных. IEnumerable
наследует от IQueryable
, поэтому IQueryable
содержит все функции IEnumerable
. Основное различие между IQueryable
и IEnumerable
заключается в том, что IQueryable
выполняет запрос с фильтрами, тогда как IEnumerable
сначала выполняет запрос, а затем фильтрует данные на основе условий.
Найти более подробное разграничение ниже:
IEnumerable
IEnumerable
существует в пространстве имен System.Collections
IEnumerable
выполняет запрос на выборку на стороне сервера, загружает данные в память на стороне клиента и затем фильтрует данныеIEnumerable
подходит для запроса данных из коллекций в памяти, таких как List, ArrayIEnumerable
полезен для запросов LINQ to Object и LINQ to XMLIQueryable
IQueryable
существует в пространстве имен System.Linq
IQueryable
выполняет "запрос на выборку" на стороне сервера со всеми фильтрамиIQueryable
подходит для запроса данных из коллекций вне памяти (например, удаленная база данных, служба)IQueryable
полезен для запросов LINQ to SQL Таким образом, IEnumerable
обычно используется для обработки коллекций в памяти, тогда как IQueryable
обычно используется для манипулирования коллекциями.
IQueryable работает быстрее, чем IEnumerable, если мы имеем дело с огромными объемами данных из базы данных, потому что IQueryable получает только необходимые данные из базы данных, а IEnumerable получает все данные независимо от необходимости из базы данных.
ienumerable: когда мы хотим иметь дело с inprocess-памятью, то есть без привязки данных iqueryable: когда нужно иметь дело с сервером sql, то есть с подключением к данным ilist: операции, такие как добавление объекта, удаление объекта и т.д.