SELECT [m].[Id], [m].[Name], [m].[TimeStamp], [t].[Id], [t].[Color],
[t].[IsDrivable],
[t].[MakeId], [t].[PetName], [t].[TimeStamp]
FROM [dbo].[Makes] AS [m]
LEFT JOIN (
SELECT [i].[Id], [i].[Color], [i].[IsDrivable], [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]
Изменение запроса на разделенный приводит к выдаче такого кода SQL (получен с использованием профилировщика SQL Server):
SELECT [m].[Id], [m].[Name], [m].[TimeStamp]
FROM [dbo].[Makes] AS [m]
ORDER BY [m].[Id]
SELECT [t].[Id], [t].[Color], [t].[IsDrivable], [t].[MakeId],
[t].[PetName], [t].
[TimeStamp], [m].[Id]
FROM [dbo].[Makes] AS [m]
INNER JOIN (
SELECT [i].[Id], [i].[Color], [i].[IsDrivable], [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]
Явная загрузка связанных данных
Если связанные данные нужно загрузить сразу после того, как главная сущность была запрошена в память, то связанные сущности можно извлечь из базы данных с помощью последующих обращений к базе данных. Это запускается с применением метода
Entry()
класса, производного от
DbContext
. При загрузке сущностей на стороне "многие" отношения "один ко многим" используйте вызов метода
Collection()
на результате
Entry()
. Чтобы загрузить сущности на стороне "один" отношения "один ко многим" (или отношения "один к одному"), применяйте метод
Reference()
. Вызов метода
Query()
на результате
Collection()
или
Reference()
возвращает экземпляр реализации
IQueryable<T>
, который можно использовать для получения строки запроса (как видно в приводимых далее тестах) и для управления фильтрами запросов (как показано в следующем разделе). Чтобы выполнить запрос и загрузить запись (записи), вызовите метод
Load()
на результате метода
Collection()
,
Reference()
или
Query()
. Выполнение запроса начнется немедленно после вызова
Load()
.
Представленный ниже тест (из
CarTests.cs
) демонстрирует, каким образом загрузить связанные данные через навигационное свойство типа ссылки внутри сущности
Car
:
[Fact]
public void ShouldGetReferenceRelatedInformationExplicitly()
{
var car = Context.Cars.First(x => x.Id == 1);
Assert.Null(car.MakeNavigation);
var query = Context.Entry(car).<b>Reference(c => c.MakeNavigation)</b>.Query();
var qs = query.ToQueryString();
query.<b>Load()</b>;
Assert.NotNull(car.MakeNavigation);
}
Вот сгенерированный код SQL:
DECLARE @__p_0 int = 1;
SELECT [m].[Id], [m].[Name], [m].[TimeStamp]
FROM [dbo].[Makes] AS [m]
WHERE [m].[Id] = @__p_0
В следующем тесте показано, как загрузить связанные данные через навигационное свойство типа коллекции внутри сущности
Car
:
[Fact]
public void ShouldGetCollectionRelatedInformationExplicitly()
{
var car = Context.Cars.First(x => x.Id == 1);
Assert.Empty(car.Orders);
var query = Context.Entry(car).<b>Collection(c => c.Orders)</b>.Query();
var qs = query.ToQueryString();
query.<b>Load()</b>;
Assert.Single(car.Orders);
}
Сгенерированный код SQL выглядит так:
DECLARE @__p_0 int = 1;
SELECT [o].[Id], [o].[CarId], [o].[CustomerId], [o].[TimeStamp]
FROM [Dbo].[Orders] AS [o]
INNER JOIN (
SELECT [i].[Id], [i].[IsDrivable]
FROM [dbo].[Inventory] AS [i]
WHERE [i].[IsDrivable] = CAST(1 AS bit)
) AS [t] ON [o].[CarId] = [t].[Id]
WHERE ([t].[IsDrivable] = CAST(1 AS bit)) AND ([o].[CarId] = @__p_0)
Явная загрузка связанных данных с фильтрами запросов
Глобальные фильтры запросов активны не только при формировании запросов, генерируемых для энергичной загрузки связанных данных, но и при явной загрузке связанных данных. Добавьте (в
MakeTests.cs
) приведенный далее тест:
[Theory]
[InlineData(1,1)]