Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

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).Reference(c => c.MakeNavigation).Query;

var qs = query.ToQueryString;

query.Load;

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).Collection(c => c.Orders).Query;

var qs = query.ToQueryString;

query.Load;

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)]

[InlineData(2,1)]

[InlineData(3,1)]

[InlineData(4,2)]

[InlineData(5,3)]

[InlineData(6,1)]

public void ShouldGetAllCarsForAMakeExplicitlyWithQueryFilters(

int makeId, int carCount)

{

var make = Context.Makes.First(x => x.Id == makeId);

IQueryable<Car> query = Context.Entry(make).Collection(c => c.Cars).Query;

var qs = query.ToQueryString;

query.Load;

Assert.Equal(carCount,make.Cars.Count);

}

Этот тест похож на тест

ShouldGetTheCarsByMake
из раздела "Фильтрация записей" ранее в главе. Однако вместо того, чтобы просто получить записи
Car
, которые имеют определенное значение
MakeId
, текущий тест сначала получает запись
Make
и затем явно загружает записи
Car
для находящейся в памяти записи
Make
. Ниже показан сгенерированный код SQL:

DECLARE @__p_0 int = 5;

SELECT [i].[Id], [i].[Color], [i].[IsDrivable], [i].[MakeId],

[i].[PetName], [i].[TimeStamp]

FROM [dbo].[Inventory] AS [i]

WHERE ([i].[IsDrivable] = CAST(1 AS bit)) AND ([i].[MakeId] = @__p_0)

Обратите внимание на то, что фильтр запросов по-прежнему применяется, хотя главной сущностью в запросе является запись

Make
. Для отключения фильтров запросов при явной загрузке записей вызовите
IgnoreQueryFilters
в сочетании с методом
Query
. Вот тест, который отключает фильтры запросов (находится в
MakeTests.cs
):

[Theory]

[InlineData(1, 2)]

[InlineData(2, 1)]

[InlineData(3, 1)]

[InlineData(4, 2)]

[InlineData(5, 3)]

[InlineData(6, 1)]

public void ShouldGetAllCarsForAMakeExplicitly(int makeId, int carCount)

{

var make = Context.Makes.First(x => x.Id == makeId);

IQueryable<Car> query =

Поделиться с друзьями: