Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

4 года назад
Открыть в
День 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