День 1161. #ЗаметкиНаПолях
Мягкое удаление в Entity Framework
При использовании мягкого удаления возникает проблема, что во всех запросах приходится отфильтровывать удалённые объекты:
dbSet.Where(x => x.Deleted == null);
И об этом нужно постоянно помнить.
Есть отличный способ решить эту проблему с помощью так называемых «глобальных фильтров запросов». В документации даже есть пример: docs.microsoft.com/en-us/e…/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() в запросе.
Источник: dotnetcoretutorials.com/2022/03…entities