Будет ли работать запрос в EF Core без Include?
Что проверяют
Знаете ли вы, как EF Core загружает связанные данные, и понимаете ли, что по умолчанию ленивой загрузки нет. Следом спрашивают про N+1 и про случаи, когда Include вообще не нужен.
Как отвечать
Запрос выполнится без ошибок, просто навигационные свойства не заполнятся: ссылка останется null, коллекция будет пустой или null, смотря как она инициализирована в классе. Способов получить связанные данные четыре:
- eager loading:
IncludeиThenInclude, данные приходят одним запросом через JOIN. При нескольких коллекциях строки перемножаются, тогда помогаетAsSplitQuery(); - explicit loading:
context.Entry(order).Collection(o => o.Items).LoadAsync()или.Reference(...), отдельный запрос по требованию; - lazy loading: выключена по умолчанию. Включается пакетом
Microsoft.EntityFrameworkCore.Proxiesи вызовомUseLazyLoadingProxies(), навигации должны бытьvirtual. Каждое обращение к незагруженному свойству даёт отдельный запрос; - проекция:
Select(o => new { o.Id, Count = o.Items.Count })работает безInclude, EF сам построит JOIN или подзапрос и заберёт только нужные колонки.Includeпри проекции в DTO игнорируется.
Стоит упомянуть ещё два поведения. Фильтр по навигации в Where тоже работает без Include, он транслируется в SQL. А если связанные сущности уже отслеживаются контекстом, EF расставит ссылки сам (relationship fix-up), и код «случайно работает», пока контекст не окажется новым. Owned-типы загружаются всегда, для них Include не пишут.
Где спотыкаются
Отвечают «без Include будет ошибка» или, наоборот, «EF подгрузит сам». Первое неверно, второе верно только при включённых прокси.
Включают lazy loading и получают N+1: список из 100 заказов, в цикле обращение к Items, в итоге 101 запрос к базе. Замечают это только под нагрузкой или в логах SQL.
Пишут Include там, где нужна проекция. Тянут целые графы сущностей ради двух полей и заодно отслеживание изменений, хотя для чтения хватило бы Select и AsNoTracking().