Ответ
Данные материализуются в объекты приложения в момент выполнения запроса (например, при вызове ToList(), FirstOrDefault(), foreach). Этот процесс называется материализацией (Materialization).
Последовательность шагов:
- Построение и выполнение SQL: Ваш LINQ-запрос преобразуется EF Core в SQL-команду и выполняется против базы данных.
- Чтение результатов: Данные возвращаются в виде
DbDataReader. - Материализация: Строки результата последовательно преобразуются в экземпляры классов сущностей.
Наглядный пример:
// Запрос НЕ выполняется здесь — это просто построение выражения IQueryable.
var query = context.Products.Where(p => p.Price > 100);
// В ЭТОТ МОМЕНТ происходит переход данных из БД в приложение:
// 1. Генерируется и выполняется SQL: SELECT * FROM Products WHERE Price > 100
// 2. Данные читаются из потока результатов.
// 3. Для каждой строки создаётся объект Product.
var expensiveProducts = query.ToList();
Что влияет на момент и способ загрузки данных?
- Отложенная загрузка (Lazy Loading): Связанные сущности (например,
Product.Category) загружаются автоматически при первом обращении к свойству навигации, что приводит к дополнительным запросам к БД. - Жадная загрузка (Eager Loading): Связанные данные загружаются одним запросом с помощью метода
Include. Данные материализуются вместе с основной сущностью.var productsWithCategory = context.Products .Include(p => p.Category) // JOIN с таблицей Categories .ToList(); // Категория загружается и материализуется одновременно с продуктом - Явная загрузка (Explicit Loading): Вы управляете моментом загрузки связанных данных с помощью метода
Load().
Оптимизация: Для сценариев "только для чтения" используйте .AsNoTracking(), чтобы отключить отслеживание изменений и ускорить материализацию.