Мягкое удаление в Entity Framework
При использовании мягкого удаления возникает проблема, что во всех запросах приходится отфильтровывать удалённые объекты:
dbSet.Where(x => x.Deleted == null);
И об этом нужно постоянно помнить.
Есть отличный способ решить эту проблему с помощью так называемых «глобальных фильтров запросов». В документации даже есть пример: https://docs.microsoft.com/en-us/ef/core/querying/filters.
Проблема в том, что в примере показано, как это сделать для отдельного объекта. Если в вашей базе данных много таблиц вам придется каждый раз не забывать добавлять конфигурацию. Придётся сделать кое-что посложнее в методе
OnModelCreating контекста:protected override void
OnModelCreating(ModelBuilder builder)
{
// остальные настройки
var entities = builder.Model
.GetEntityTypes()
.Where(e => e.ClrType.BaseType == typeof(Auditable))
.Select(e => e.ClrType);
Expression<Func<Auditable, bool>>
expression = del => del.Deleted == null;
foreach (var e in entities)
{
var p = Expression.Parameter(e);
var body =
ReplacingExpressionVisitor
.Replace(expression.Parameters.Single(),
p, expression.Body);
builder.Entity(entity)
.HasQueryFilter(
Expression.Lambda(body, p));
}
base.OnModelCreating(builder);
}
}
Сначала мы выбираем все сущности, которые наследуют от
Auditable (см. предыдущий пост). Затем создаём выражение expression для фильтрации. Далее перебираем все выбранные сущности и создаём для каждого типа своё выражение путём замены параметра выражения expression на тип конкретной сущности. И наконец с помощью метода HasQueryFilter() добавляем глобальный фильтр.Теперь все запросы в нашем приложении будут иметь фильтр и не включать мягко удалённые объекты. Если же для каких-то запросов (например, в блоке администрирования) всё-таки нужно получить все объекты, можно использовать метод
IgnoreQueryFilters() в запросе.Источник: https://dotnetcoretutorials.com/2022/03/17/using-ef-core-global-query-filters-to-ignore-soft-deleted-entities/