Придерживаясь в книге темы автомобилей, предположим, что все записи Car, которые не являются управляемыми, должны отфильтровываться из нормальных запросов. Вот как можно добавить глобальный фильтр запросов с использованием Fluent API:

modelBuilder.Entity(entity =>

{

  entity.HasQueryFilter(c => c.IsDrivable == true);

  entity.Property(p => p.IsDrivable).HasField("_isDrivable").

    HasDefaultValue(true);

});

Благодаря такому глобальному фильтру запросов запросы, вовлекающие сущность Car, будут автоматически отфильтровывать неуправляемые автомобили. Скажем, запуск следующего запроса LINQ:

var cars = Context.Cars.ToList;

приводит к выполнению показанного ниже оператора SQL:

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)

Если вам нужно просмотреть отфильтрованные записи, тогда добавьте в запрос LINQ вызов IgnoreQueryFilters, который отключает глобальные фильтры запросов для каждой сущности в запросе LINQ. Запуск представленного далее запроса LINQ:

var cars = Context.Cars.IgnoreQueryFilters.ToList;

инициирует выполнение следующего оператора SQL:

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

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

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

Важно отметить, что вызов IgnoreQueryFilters удаляет фильтр запросов для всех сущностей в запросе LINQ, в том числе и тех, которые задействованы в вызовах Include или Thenlnclude.

<p id="AutBody_Root934"><strong>Глобальные фильтры запросов на навигационных свойствах</strong></p>

Глобальные фильтры запросов можно также устанавливать на навигационных свойствах. Пусть вам необходимо отфильтровать любые заказы, которые содержат экземпляр Car, представляющий неуправляемый автомобиль. Фильтр создается на навигационном свойстве CarNavigation сущности Order:

modelBuilder.Entity.HasQueryFilter(e => e.CarNavigation.IsDrivable);

При выполнении стандартного запроса LINQ любые заказы, содержащие неуправляемый автомобиль, будут исключаться из результата. Ниже показан оператор LINQ и генерированный оператор SQL:

// Код C#

var orders = Context.Orders.ToList;

/* Сгенерированный запрос SQL */

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)

Для удаления фильтра запросов используйте вызов IgnoreQueryFilters. Вот как выглядит модифицированный оператор LINQ и сгенерированный запрос SQL:

// Код C#

var orders = Context.Orders.IgnoreQueryFilters.ToList;

/* Сгенерированный запрос SQL */

SELECT [o].[Id], [o].[CarId], [o].[CustomerId], [o].[TimeStamp]

FROM [Dbo].[Orders] AS [o]

Здесь уместно предостеречь: исполняющая среда EF Core не обнаруживает циклические глобальные фильтры запросов, поэтому при добавлении фильтров запросов к навигационным свойствам соблюдайте осторожность.

<p id="AutBody_Root935"><strong>Явная загрузка с глобальными фильтрами запросов</strong></p>

Глобальные фильтры запросов действуют и при явной загрузке связанных данных. Например, если вы хотите загрузить записи Car для Make, то фильтр IsDrivable предотвратит загрузку в память записей, представляющих неуправляемые автомобили. В качестве примера взгляните на следующий фрагмент кода:

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

Context.Entry(make).Collection(c=>c.Cars).Load;

К настоящему моменту не должен вызывать удивление тот факт, что сгенерированный оператор SQL включает фильтр для неуправляемых автомобилей:

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

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