0Pricing
C# Academy · Урок

Деревья выражений в поставщиках LINQ

Узнайте, как поставщики преобразуют выражения в запросы.

«Деревья выражений в поставщиках LINQ» — бесплатный урок C# Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 4 уроков всего.

Зачем LINQ нужны деревья выражений

У LINQ есть два варианта. IEnumerable<T> выполняет лямбды в памяти. IQueryable<T> получает их как деревья выражений, чтобы провайдер мог преобразовать их в другой язык, например SQL.

IEnumerable и IQueryable

Разница заключается в типе параметра: IEnumerable.Where принимает Func<T,bool> (скомпилированный код), а IQueryable.Where принимает Expression<Func<T,bool>> (дерево).

using System;
using System.Linq;
using System.Linq.Expressions;

int[] nums = { 1, 2, 3, 4 };
// IEnumerable path: lambda is a compiled delegate
var evens = nums.Where(n => n % 2 == 0);
Console.WriteLine(string.Join(",", evens)); // 2,4

Запрос остаётся данными

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

using System;
using System.Linq;
using System.Linq.Expressions;

IQueryable<int> q = new[] { 1, 2, 3, 4, 5 }.AsQueryable();
var filtered = q.Where(n => n > 2);
Console.WriteLine(filtered.Expression.NodeType); // Call (a method-call tree)

Проверка выражения запроса

Свойство Expression объекта, поддерживающего запросы, предоставляет дерево, которое провайдер преобразует.

using System;
using System.Linq;

var q = new[] { 10, 20, 30 }.AsQueryable().Where(x => x >= 20);
Console.WriteLine(q.Expression.ToString().Contains("Where")); // True

Преобразование, а не выполнение

Провайдер, например Entity Framework, обходит дерево и формирует SQL, такой как WHERE Age > 18. Ваш предикат C# не выполняется на клиенте: эту работу выполняет база данных.

Роль IQueryProvider

IQueryable содержит IQueryProvider. Когда Вы перебираете запрос, провайдер получает дерево выражений и решает, как его выполнить.

using System;
using System.Linq;

var q = new[] { 1, 2, 3 }.AsQueryable();
Console.WriteLine(q.Provider.GetType().Name); // EnumerableQuery (the in-memory provider)

Отложенное выполнение

Дерево преобразуется и выполняется только при переборе (например, с помощью ToList или foreach). До этого момента оно является обычными данными, которые можно продолжать объединять.

using System;
using System.Linq;

var q = new[] { 1, 2, 3, 4 }.AsQueryable()
    .Where(n => n > 1)
    .Select(n => n * 10);
// nothing has run yet; now force it:
Console.WriteLine(string.Join(",", q.ToList())); // 20,30,40

Составление запросов

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

using System;
using System.Linq;

var baseQuery = new[] { 5, 15, 25, 35 }.AsQueryable();
var q = baseQuery.Where(n => n > 10);
q = q.Where(n => n < 30); // composed: 10 < n < 30
Console.WriteLine(string.Join(",", q.ToList())); // 15,25

Что нельзя преобразовать

Провайдеры могут преобразовать только те операции, которые им понятны. Предикат, вызывающий произвольный метод C#, может вызвать исключение во время выполнения, поскольку ему нет эквивалента в SQL.

Создание собственного провайдера

Пользовательские провайдеры реализуют IQueryProvider и используют ExpressionVisitor, чтобы обойти дерево и преобразовать каждый узел в целевой язык запросов.

Объединение всех элементов

Здесь показана ключевая идея: одна и та же лямбда является делегатом для IEnumerable, но деревом для IQueryable, что позволяет выполнять преобразование.

using System;
using System.Linq;
using System.Linq.Expressions;

Expression<Func<int, bool>> predicate = n => n > 2;
var data = new[] { 1, 2, 3, 4 };
// IEnumerable needs a delegate:
Console.WriteLine(string.Join(",", data.Where(predicate.Compile()))); // 3,4
// IQueryable accepts the tree directly:
Console.WriteLine(string.Join(",", data.AsQueryable().Where(predicate))); // 3,4

Быстрая проверка

Убедитесь, что понимаете роль деревьев выражений в провайдерах LINQ.

Повторение

Вы узнали, как провайдеры LINQ используют деревья выражений.

  • IEnumerable использует скомпилированный Func, а IQueryable — деревья Expression<Func>.
  • Провайдеры преобразуют дерево (например, в SQL), а не выполняют его.
  • Выполнение откладывается до перебора.
  • Работают только преобразуемые операции; произвольные методы могут вызвать ошибку.

Часто задаваемые вопросы

Урок «Деревья выражений в поставщиках LINQ» бесплатный?

Да — полный текст урока «Деревья выражений в поставщиках LINQ» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 4 уроков всего.

Чему я научусь в уроке «Деревья выражений в поставщиках LINQ»?

Узнайте, как поставщики преобразуют выражения в запросы. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C# Academy?

Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Деревья выражений в поставщиках LINQ»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C# Academy?

Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Что такое деревья выражений
  2. Построение выражений вручную
  3. Компиляция и выполнение выражений
  4. Деревья выражений в поставщиках LINQ
← Назад к C# Academy