.NET IEnumerable, что это такое?

Я пытаюсь понять, что такое IEnumerable<>.

Я думал, что это просто интерфейс, говорящий, что базовая структура данных имеет эти методы, например First() и т. д.

Однако я протестировал показанный здесь код в EF, который, как я ожидал, создаст запрос TOP в БД, как если бы он выполнялся как IQueryable, но вместо этого он заставляет его извлекать всю таблицу в памяти для выполнения своей операции.

 IEnumerable<EntityObject> m = DbContext.GetDbSet<EntityObject>();
 var x = m.First();

Так заставляет ли обработка чего-либо как IEnumerable работать как массив, список или что-то в этом роде?

Примечание. Мне НЕ нужно знать, как оптимизировать запрос, чтобы он был более производительным. Я пытаюсь понять, почему просто рассматривать его как другой интерфейс и использовать одни и те же методы приводит к другой базовой логике.

Если что-то является IEnumerable, вы можете использовать его в цикле foreach. Другими словами, вы можете перечислить это.

Brian Rogers 03.07.2024 04:36

Перечисляемый объект может позволить вам выполнять бесконечные итерации, например: static IEnumerable<int> Values() { for (int i = 0; ; ++i) { yield return i; } }

ProgrammingLlama 03.07.2024 04:39

«Что такое IEnumerable<>» и то, что EF делает для его поддержки, — это две совершенно разные вещи.

Henk Holterman 03.07.2024 04:57

Попробуйте m = DbContext.GetDbSet<EntityObject>().Take(1);

Henk Holterman 03.07.2024 04:59

@HenkHolterman «Что такое IEnumerable<>» и то, что EF делает для его поддержки, - это две разные вещи». IEnumerable и IQueryable имеют операцию First, я бы подумал, что каким бы ни был тип данных EF внизу, интерфейсы будут вызывая одни и те же операции First, делая то же самое. Как структура данных EF может делать что-то еще на основе одного и того же вызова метода разными интерфейсами?

F Dev 03.07.2024 05:37

m = DbContext.GetDbSet<EntityObject>().Take(1); это будет делать top(1), потому что он не обрабатывается как IEnumerable, я это уже понимаю, это будет то же самое, как если бы мы сделали first или что-то еще. Я не пытаюсь генерировать эффективный sql, я просто пытаюсь понять, что такое IEnumerable, поскольку он не соответствует тому, как, по моему мнению, он должен работать.

F Dev 03.07.2024 05:38

Вы должны спросить о разнице между IEnumerable и IQueryablemedium.com/@shahrukhkhon_7802/…IQueryable методы фиксируют ваше намерение, чтобы его можно было преобразовать в sql, IEnumerable методы оптимизированы для выполнения в памяти. Отношение к IQueryable как к IEnumerable уничтожит его преимущества.

Jeremy Lakeman 03.07.2024 06:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
7
187
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

.Net IEnumerable, что это такое?

Как @ProgrammingLlama и @Henk Holterman уже дали вам первоначальное представление, однако я пытаюсь расширить его немного больше.

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

То же самое касается и того, что что-то рассматривается как IEnumerable, что заставляет его работать. как массив или список или что-то в этом роде?

На самом деле, простое присвоение IQueryable<T>IEnumerable<T> не приводит к немедленному выполнению запроса и загрузке данных в память. Именно последующие операции, такие как вызов First(), вызывают выполнение запроса и загрузку данных в память.

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

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

Итак, вы можете изменить свой код следующим образом:

IQueryable<EntityObject> m = DbContext.GetDbSet<EntityObject>();
var x = m.First();

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

«На самом деле, это заставляет запрос выполняться немедленно и загружать результаты в память». Нет, это не так. Просто присвоение переменной типа IEnumerable<T> этого не сделает. Когда вы используете данные, представленные IEnumerable<T>, эти данные будут принудительно загружены. Да, дальнейшие операции, такие как Where и т. д., будут выполняться в памяти, но это не означает, что данные загружаются в тот момент, когда выполняется присвоение IEnumerable<T>.

Jon Skeet 03.07.2024 08:07

@JonSkeet Рад получить ваше мнение по этому поводу, я бы обновил свой ответ.

Md Farid Uddin Kiron 03.07.2024 08:24

Гораздо лучше, спасибо за обновление.

Jon Skeet 03.07.2024 08:31

Спасибо @JonSkeet за то, что указали на это, и ваше предложение — благословение для меня. Прошло 8 лет с тех пор, как я слежу за вами, вашим блогом, github.

Md Farid Uddin Kiron 03.07.2024 08:46
Ответ принят как подходящий

Пришлось немного покопаться в методах декомпилятора. Насколько я могу судить, причина разницы в функциональности на самом деле связана с тем, что IEnumerables и IQueryables имеют разные методы расширения.

Похоже, в самих интерфейсах мало что происходит. Это объясняет мои первоначальные опасения, поскольку я не мог понять, как простое обращение с ним как с другим интерфейсом может повлиять на выполняемые над ним операции.

Методы расширения IQueryables заставляют его выполнять выражения, которые ему необходимо запросить, тогда как выражения Enumerable предлагают использовать GetEnumerator и перемещаться по ним с помощью MoveNext(), что, по-видимому, инициирует запрос при первом вызове.

Да, хорошая попытка, однако я имел в виду именно это. В любом случае, рад видеть, что у вас это тоже есть.

Md Farid Uddin Kiron 03.07.2024 07:32

Другие вопросы по теме

Разница между вызовом асинхронного метода и переносом вызова в Task.Run
Создать каталог, только если он не существует (.NET)
Foreach нельзя использовать для переменных типа «PropertyInfo», поскольку «PropertyInfo» не имеет определения для «GetEnumerator»
Положение большого пальца динамической сетки данных WPF изменилось, когда определение строки и столбца добавляется в выбранную динамическую сетку
Указание симулятора IOS при запуске приложения с помощью инструментов командной строки .NET
Код ошибки MSB4062 в проекте функции Azure в VS для запуска API Microsoft Graph с функциями Azure
Отключить закрытие начальной загрузки вне холста при щелчке по фону в приложении Blazor .NET
Целые числа, допускающие значение NULL – почему не возникает исключение?
Можем ли мы предоставить участнику данных BLOB-объектов хранилища разрешение на регистрацию приложения Azure?
Как запустить EF Core ExecuteUpdateAsync и добавить новый объект как часть этого обновления?