.Include(c => c.MakeNavigation)

  .Include(c => c.Orders).ThenInclude(o => o.CustomerNavigation).ToList();

<p id="AutBody_Root929"><strong>Фильтрованные включаемые данные</strong></p>

В версии EF Core 5 появилась возможность фильтрации и сортировки включаемых данных. Допустимыми операциями при навигации по коллекции являются Where(), OrderBy(), OrderByDescending(), ThenBy(), ThenByDescending(), Skip() и Take(). Например, если нужно получить все записи Make, но только со связанными записями Car с желтым цветом, тогда вы организуете фильтрацию навигационного свойства в лямбда-выражении такого вида:

var query = Context.Makes

    .Include(x => x.Cars.Where(x=>x.Color == "Yellow")).ToList();

В результате запустится следующий запрос:

SELECT [m].[Id], [m].[Name], [m].[TimeStamp], [t].[Id], [t].[Color],

  [t].[MakeId], [t].[PetName], [t].[TimeStamp]

FROM [dbo].[Makes] AS [m]

LEFT JOIN (

  SELECT [i].[Id], [i].[Color], [i].[MakeId], [i].[PetName], [i].[TimeStamp]

    FROM [Dbo].[Inventory] AS [i]

    WHERE [i].[Color] = N'Yellow') AS [t] ON [m].[Id] = [t].[MakeId]

ORDER BY [m].[Id], [t].[Id]

<p id="AutBody_Root930"><strong>Энергичная загрузка с разделением запросов</strong></p>

Наличие в запросе LINQ множества вызовов Include() может отрицательно повлиять на производительность. Для решения проблемы в EF Core 5 были введены разделяемые запросы. Вместо выполнения одиночного запроса исполняющая среда EF Core будет разделять запрос LINQ на несколько запросов SQL и затем объединять все связанные данные. Скажем, добавив к запросу LINQ вызов AsSplitQuery(), можно ожидать, что предыдущий запрос будет представлен в виде множества запросов SQL:

var query = Context.Makes.AsSplitQuery()

  .Include(x => x.Cars.Where(x=>x.Color == "Yellow")).ToList();

Вот как выглядят выполняемые запросы:

SELECT [m].[Id], [m].[Name], [m].[TimeStamp]

FROM [dbo].[Makes] AS [m]

ORDER BY [m].[Id]

SELECT [t].[Id], [t].[Color], [t].[MakeId], [t].[PetName],

       [t].[TimeStamp], [m].[Id]

FROM [dbo].[Makes] AS [m]

INNER JOIN (

    SELECT [i].[Id], [i].[Color], [i].[MakeId], [i].[PetName], [i].[TimeStamp]

    FROM [Dbo].[Inventory] AS [i]

    WHERE [i].[Color] = N'Yellow'

) AS [t] ON [m].[Id] = [t].[MakeId]

ORDER BY [m].[Id]

Применению разделяемых запросов присущ и недостаток: если данные изменяются между выполнением запросов, тогда возвращаемые данные будут несогласованными.

<p id="AutBody_Root931"><strong>Явная загрузка</strong></p>

Явная загрузка — это загрузка данных по навигационному свойству после того, как главный объект уже загружен. Такой процесс включает в себя дополнительное обращение к базе данных для получения связанных данных. Прием может быть удобен, если приложению необходимо получать связанные записи выборочно на основе какого-то действия пользователя, а не извлекать все связанные записи.

Процесс начинается с уже загруженной сущности и использования метода Entry() на экземпляре производного от DbContext класса. При запросе в отношении навигационного свойства типа ссылки (например, с целью получения информации Make для автомобиля) применяйте метод Reference(). При запросе в отношении навигационного свойства типа коллекции используйте метод Collection(). Выполнение запроса откладывается до вызова Load(), ToList() или агрегирующей функции (вроде Count() либо Мах()).

В следующих примерах показано, как получить связанные данные о производителе и заказах для записи Car:

// Получить запись Car.

var car = Context.Cars.First(x => x.Id == 1);

// Получить информацию о производителе.

Context.Entry(car).Reference(c => c.MakeNavigation).Load();

// Получить заказы, к которым относится данная запись Car.

Context.Entry(car).Collection(c => c.Orders).Query().

Перейти на страницу:

Похожие книги