Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю
Придерживаясь в книге темы автомобилей, предположим, что все записи
Car
modelBuilder.Entity<Car>(entity =>
{
<b> entity.HasQueryFilter(c => c.IsDrivable == true);</b>
entity.Property(p => p.IsDrivable).HasField("_isDrivable").
HasDefaultValue(true);
});
Благодаря такому глобальному фильтру запросов запросы, вовлекающие сущность
Car
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()
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()
Include()
Thenlnclude()
Глобальные фильтры запросов на навигационных свойствах
Глобальные фильтры запросов можно также устанавливать на навигационных свойствах. Пусть вам необходимо отфильтровать любые заказы, которые содержат экземпляр
Car
CarNavigation
Order
modelBuilder.Entity<Order>().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()
// Код C#
var orders = Context.Orders.IgnoreQueryFilters().ToList();
/* Сгенерированный запрос SQL */
SELECT [o].[Id], [o].[CarId], [o].[CustomerId], [o].[TimeStamp]
FROM [Dbo].[Orders] AS [o]
Здесь уместно предостеречь: исполняющая среда EF Core не обнаруживает циклические глобальные фильтры запросов, поэтому при добавлении фильтров запросов к навигационным свойствам соблюдайте осторожность.
Явная загрузка с глобальными фильтрами запросов
Глобальные фильтры запросов действуют и при явной загрузке связанных данных. Например, если вы хотите загрузить записи
Car
Make
IsDrivable
var make = Context.Makes.First(x => x.Id == makeId);
Context.Entry(make).Collection(c=>c.Cars).Load();
К настоящему моменту не должен вызывать удивление тот факт, что сгенерированный оператор 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)) AND ([i].[MakeId] = 1
С игнорированием фильтров запросов при явной загрузке данных связана небольшая загвоздка. Возвращаемым типом метода
Collection()
CollectionEntry<Make,Car>
IQueryable<T>
IgnoreQueryFilters()
Query()
IQueryable<Car>
var make = Context.Makes.First(x => x.Id == makeId);
Context.Entry(make).Collection(c=>c.Cars).Query().IgnoreQueryFilters().Load();