Найти в Дзене
Архитектура на .NET

Глобальные фильтры в EF Core

Естественным выбором ORM для приложения на .net является EF Core. Эта ORM поддерживает много неочевидных и интересных возможностей, облегчающих решение повседневных задач.

Сегодня разберём применение глобальных фильтров.

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

  • Ваше приложение поддерживает несколько тенантов
  • Ваше приложение использует мягкое удаление с помощью флага Deleted
  • Ваши сущности привязаны к пользователю через поле UserId и вы хотите фильтровать выдачу пользователя


Во всех подобных случаях возникает необходимость добавления дополнительных условий в каждый запрос. Для простоты разберём на примере флага
Deleted.

Предположим, у вас есть сущность заказа
Order:

Всякий раз, запрашивая список заказов, вам необходимо добавлять условие .Where(order => !order.Deleted). Делать это придётся вне зависимости от того, используете ли вы паттерн Спецификация, или строите свои запросы напрямую над DbSet:

-2

При таком подходе возникает две проблемы:

  1. Риск пропустить проверку флага, и тогда в выдачу попадут удалённые сущности
  2. Дублирование проверки флага во многих местах программы. Если условие более сложное, проблема с дублированием усугубляется.

Чтобы решить обе эти проблемы, достаточно использовать глобальный фильтр, объявить который можно в классе-наследнике DbContext:

-3

Теперь можно убрать условие .Where(order => !order.Deleted) изо всех остальных запросов, это условие будет применяться автоматически!

Но остаётся вопрос, а как же в таком случае вывести список именно удалённых заказов? Использовать операцию
.IgnoreQueryFilters():

-4