Pular para o conteúdo principal
Versão: main (dev) 🚧

ITLab.Template.DevPack.Infrastructure.EfCore.Interceptors

Implements EF Core SaveChanges interceptors for cross-cutting persistence behaviors.

Componentes

TipoNomeResponsabilidade
ClassAuditableEntityInterceptorApplies created/updated metadata for IAuditable entities before each save
ClassSoftDeleteInterceptorConverts hard deletes to soft-delete updates for ISoftDeletable entities
ClassMultiTenantEntityInterceptorStamps IMultiTenant.TenantId on insert and blocks cross-tenant modify/delete
ClassDispatchDomainEventsInterceptorPublishes and clears domain events from tracked entities after save

Como usar

// Interceptors are additive and can be chained.
options.AddInterceptors(
auditableInterceptor,
softDeleteInterceptor,
dispatchDomainEventsInterceptor);

MultiTenantEntityInterceptor — stamping + guard (10.5.0)

Write-side da tenancy, par do read-side global query filter (MultiTenantModelBuilderExtensions, ver ../README.md):

  • Insert: entidade IMultiTenant com TenantId nulo/0 recebe o tenant corrente via reflexão (ObjectHelper.TrySetProperty, mesma mecânica de EntityHelper.TrySetTenantId). Defesa em profundidade além do ctor Entity().
  • Modify/Delete cross-tenant: se TenantId != tenant corrente, lança InvalidOperationException — o filtro de leitura não cobre uma entidade carregada num escopo e salva em outro.
  • Sem tenant corrente (null/0 = host/global): no-op.
services.AddDevPackEfCoreInterceptors()
.WithAuditableEntityInterceptor()
.WithSoftDeleteInterceptor()
.WithMultiTenantInterceptor() // após soft-delete, antes do dispatch
.WithDispatchDomainEventsInterceptor();

Como os demais, é Singleton e resolve ICurrentUser de um escopo por-call.

O que não fazer

  • Do not depend on interceptor side effects for business invariants.
  • Do not publish integration events directly in DispatchDomainEventsInterceptor without outbox guarantees.
  • Do not rely on MultiTenantEntityInterceptor for read isolation — it is write-side only; pair it with ApplyMultiTenantQueryFilters.

Extensão pelo produto

  • Products can override behavior by replacing registrations with custom interceptor implementations.
  • If replacing, preserve the contracts of IAuditable and ISoftDeletable to keep consistency.