У меня есть linq к запросу объектов в рекурсивном цикле и боящийся, когда объекты приблизятся к более затем 1000 и более затем 100 пользователей сайта - мой веб-сайт повредится. так это возможный скомпилировать linq в запрос объектов.
Запрос linq делает ничто больше затем не находит прямых детей узла.
Чтобы понять, почему концепция компиляции на самом деле не имеет смысла для запросов LINQ to Object, полезно понять, как LINQ реализовано. Во-первых, должно быть ясно, что запросы LINQ, написанные с плавным синтаксисом, преобразуются компилятором C # в эквивалентный синтаксис вызова методов во время времени компиляции независимо от того, какой вариант LINQ вы используете:
from person in people
where person.Age < 18
select person.Name
// will be converted to:
people.Where(person => person.Age < 18).Select(person => person.Name)
С этого момента далее запрос LINQ представляет собой набор вызовов методов, принимающих некоторые аргументы и обычно преобразующих объект IEnumerable
в другой объект IEnumerable
. Отложенное выполнение, которое отличается от компиляции, просто достигается за счет того, что не берется какой-либо объект из исходного IEnumerable
, пока вы не перейдете к выходу IEnumerable
. По сути, методы с отложенным выполнением оперируют своими аргументами символически, не затрагивая исходную коллекцию, создавая генератор, который запрашивает данные по своему усмотрению.
Имея это в виду, взгляните на лямбда-выражение person => person.Age <18
в приведенном выше выражении.Он принимает объект Person
и возвращает bool
. Лямбда-выражения нетипизированы; их можно рассматривать как деревья выражений или анонимные методы в зависимости от контекста, из которого выводится их тип. В этом случае тип определяется из типа параметра метода расширения Where
. Вот где проявляется различие между LINQ to SQL и LINQ to Object. В LINQ to Objects метод Where
просто принимает Func
в отличие от Expression
. По сути, это означает, что в LINQ to Objects компилятор C # компилирует лямбда-выражение до анонимного метода и генерирует IL во время компиляции и передает делегата этому методу в Where
.
В других вариантах LINQ, таких как LINQ to SQL, лямбда не компилируется в IL. Вместо этого компилятор создает объект дерева выражения из лямбда-выражения и передает дерево выражения в методы LINQ. Методы LINQ используют эти деревья выражений для построения модели запросов. Когда запрос выполняется, объектная модель, созданная для представления запроса с использованием деревьев выражений, будет преобразована в другую вещь (в зависимости от используемого варианта LINQ), например SQL-операторы в LINQ to SQL, для выполнения в базе данных. Этот процесс преобразования выполняется во время выполнения, и это то, что мы называем компиляцией запросов LINQ .
Подводя итог, вопрос состоит в том, чтобы скомпилировать что ? Причина, по которой LINQ to Object не требует компиляции во время выполнения, заключается в том, что он изначально не в формате дерева выражений; это уже ИЛ.
Вам почти никогда не нужно беспокоиться о производительности LINQ to Objects по сравнению с обычным циклом.
Как и во всех случаях оптимизации, беспокойтесь об этом, когда доберетесь туда. С очень высокой вероятностью, если вы когда-нибудь подключите более 100 пользователей одновременно, ваше узкое место будет в совершенно другом месте.