Interceptors в EntityFramework Core или EF Core Перехватчики
Полезности | создано: 17.08.2024 | опубликовано: 15.03.2025 | обновлено: 17.03.2025 | просмотров: 82
Перехватчики Entity Framework Core (EF Core) позволяют перехватывать, изменять и (или) подавлять операции EF Core. Сюда входят низкоуровневые операции с базой данных, такие как выполнение команды, а также операции более высокого уровня, такие как вызовы SaveChanges.
Описание
Entity Framework Core (EF Core) — это мощное и гибкое объектно-реляционное сопоставление (ORM) для разработчиков .NET. Помимо своих функций, перехватчики предоставляют механизм подключения к конвейеру EF Core, позволяя разработчикам проверять, изменять или дополнять операции EF Core. В этом руководстве объясняются перехватчики, как они работают и их практическое применение с примерами.
Типы перехватчиков Interceptors
EF Core предоставляет несколько встроенных интерфейсов для определения перехватчиков:
- IDbCommandInterceptor: Для выполнения команд базы данных.
- ISaveChangesInterceptor: Для перехвата операций SaveChanges.
- IQueryExpressionInterceptor: для перехвата выражений запроса LINQ.
- IConnectionInterceptor: для операций подключения к базе данных.
- ITransactionInterceptor: Для перехвата операций, связанных с транзакциями.
Примеры
Это один из возможных примеров использования Interceptor при реализации SoftDelete. То есть, когда сущность не удаляется реально из БД, а помечается специальным образом, чтобы при выборке обычных сущностей удаленные был исключены.
public class SoftDeleteInterceptor : ISaveChangesInterceptor
{
public override int SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
{
var context = eventData.Context;
if (context == null) return base.SavingChanges(eventData, result);
foreach (var entry in context.ChangeTracker.Entries())
{
// Handle entities with IsDeleted property
if (entry.Entity is ISoftDeletable softDeletableEntity && entry.State == EntityState.Deleted)
{
entry.State = EntityState.Modified;
softDeletableEntity.IsDeleted = true;
// Update related entities if required for complex relationships
if (entry.Entity is ITenantEntity tenantEntity)
{
HandleTenantSpecificLogic(context, tenantEntity);
}
}
}
return base.SavingChanges(eventData, result);
}
private void HandleTenantSpecificLogic(DbContext context, ITenantEntity tenantEntity)
{
// Example: Ensure related tenant-specific records are soft-deleted or flagged appropriately
var relatedEntities = context.ChangeTracker.Entries()
.Where(e => e.Entity is IRelatedEntity && ((IRelatedEntity)e.Entity).TenantId == tenantEntity.TenantId);
foreach (var relatedEntity in relatedEntities)
{
if (relatedEntity.State == EntityState.Deleted)
{
relatedEntity.State = EntityState.Modified;
((IRelatedEntity)relatedEntity.Entity).IsDeleted = true;
}
}
}
}