Естественным выбором ORM для приложения на .net является EF Core. Эта ORM поддерживает много неочевидных и интересных возможностей, облегчающих решение повседневных задач.
Сегодня разберём применение глобальных фильтров.
Глобальные фильтры полезны в случаях, когда вам нужно ограничивать доступ к сущностям по определенным правилам, которые повторяются от запроса к запросу. Например:
- Ваше приложение поддерживает несколько тенантов
- Ваше приложение использует мягкое удаление с помощью флага Deleted
- Ваши сущности привязаны к пользователю через поле UserId и вы хотите фильтровать выдачу пользователя
Во всех подобных случаях возникает необходимость добавления дополнительных условий в каждый запрос. Для простоты разберём на примере флага Deleted.
Предположим, у вас есть сущность заказа Order:
Всякий раз, запрашивая список заказов, вам необходимо добавлять условие .Where(order => !order.Deleted). Делать это придётся вне зависимости от того, используете ли вы паттерн Спецификация, или строите свои запросы напрямую над DbSet:
При таком подходе возникает две проблемы:
- Риск пропустить проверку флага, и тогда в выдачу попадут удалённые сущности
- Дублирование проверки флага во многих местах программы. Если условие более сложное, проблема с дублированием усугубляется.
Чтобы решить обе эти проблемы, достаточно использовать глобальный фильтр, объявить который можно в классе-наследнике DbContext:
Теперь можно убрать условие .Where(order => !order.Deleted) изо всех остальных запросов, это условие будет применяться автоматически!
Но остаётся вопрос, а как же в таком случае вывести список именно удалённых заказов? Использовать операцию .IgnoreQueryFilters():