Ответ
Include и ThenInclude — это методы в Entity Framework Core для жадной загрузки связанных данных (Eager Loading). Их основное различие — в уровне вложенности навигационных свойств, которые они загружают.
Includeзагружает навигационное свойство первого уровня, непосредственно связанное с основным запрашиваемым объектом.ThenIncludeиспользуется для загрузки вложенных (цепочных) свойств — то есть свойств объекта, который был загружен с помощью предыдущегоIncludeилиThenInclude.
Практический пример:
// Загружаем Customers, их заказы (Orders) и детали каждого заказа (OrderDetails)
var customersWithOrders = context.Customers
.Include(c => c.Orders) // Первый уровень: заказы клиента
.ThenInclude(o => o.OrderDetails) // Второй уровень: детали заказа
.ToList();
Ключевые правила:
Includeможно использовать самостоятельно.ThenIncludeобязательно должен следовать послеIncludeили другогоThenInclude.- Порядок вызовов определяет путь загрузки: от корневого объекта к вложенным.
- Без
ThenIncludeв примере выше коллекцияOrderDetailsв каждом заказе осталась быnullили пустой (если не включена ленивая загрузка).
Ответ 18+ 🔞
Ну, смотри, чтобы не путаться в этих Include и ThenInclude, представь себе обычную ситуацию. Ты заходишь в бар, просишь счёт, а там просто итоговая сумма — нихуя не понятно, за что платить.
Include — это как сказать: «А ну-ка, бармен, разбей мне этот счёт по позициям!». То есть ты загружаешь сразу связанные данные первого уровня. Вместо того чтобы потом бегать десять раз к базе за каждой мелочью, ты всё получаешь одним здоровенным запросом.
// Без Include — получаешь просто клиента, а его заказы — null или пусто.
// С Include — получаешь клиента И ВСЕ его заказы сразу, в одном пакете.
var тупойКлиент = context.Клиенты.Find(1); // Заказов нет, нихуя не ясно.
var умныйКлиент = context.Клиенты
.Include(k => k.Заказы) // Вот тут всё, заказы уже в комплекте!
.FirstOrDefault(k => k.Id == 1);
А теперь смотри, что бывает. Ты получил счёт по позициям (Include), но каждая позиция — это, блядь, просто название напитка. А тебе-то ещё и состав коктейля надо посмотреть, кто его готовил! Вот тут на сцену выходит ThenInclude.
ThenInclude — это когда ты, получив разбивку по позициям, говоришь: «А теперь по каждой позиции покажи мне детальную рецептуру и фотку того мудака-бармена, который это смешивал». То есть ты загружаешь данные уже не от основного объекта (клиента), а от того, что ты только что подгрузил (от заказа).
// Хочешь докопаться до сути? Тогда цепляй ThenInclude.
var клиентСРазборомПолёта = context.Клиенты
.Include(k => k.Заказы) // Сначала заказы цепляешь
.ThenInclude(z => z.ДеталиЗаказа) // Потом к КАЖДОМУ заказу — его детали
.ThenInclude(d => d.Напиток) // А потом к КАЖДОЙ детали — сам напиток
.Include(k => k.ЛюбимыйБармен) // Можно и параллельно другую ветку грузить
.FirstOrDefault(k => k.Id == 1);
Главные правила, чтобы не обосраться:
Includeможно тыкать просто так, с него всё начинается.ThenInclude— это прицепной вагон. БезIncludeперед ним он нихуя не работает. Это как требовать рецепт коктейля, не заказав сам коктейль.- Цепочка
Include->ThenInclude->ThenInclude— это твой путь вглубь, как матрёшка. - Если забудешь
ThenInclude, то, получив заказы, обнаружишь, что их детали — пусты. И будешь потом в цикле дергать базу, как лох, убивая производительность.
Короче, Include грузит то, что пристёгнуто прямо к твоей сущности. А ThenInclude — это уже погружение в кроличью нору, когда тебе надо из того, что пристёгнуто, вытащить что-то ещё более глубокое. Всё просто, как три копейки.