AuditInterceptor, SaveChanges öncesinde change tracker’daki her entity’nin audit alanlarını otomatik doldurur. Audit ve soft-delete tek bir interceptor’da birleştirilmiştir — ayrı bir soft-delete interceptor’ı yoktur.
Hook noktaları
Hem async hem syncSaveChanges yakalanır; ikisi de aynı ApplyAuditFields metodunu çağırır:
ApplyAuditFields
HerEntityBase entry’sinin state’ine göre ilgili alanlar set edilir:
Deleted → Modified dönüşümü soft-delete’in kalbidir: EF Core DELETE SQL’i yerine UPDATE üretir. Detaylar Soft Delete sayfasında.DateTime.UtcNow’dır. now ve userId döngü öncesi bir kez okunur, böylece tek SaveChanges içindeki tüm satırlar tutarlı değer alır.
Aktör kimliği — IAuditUserContext
CreatedBy/UpdatedBy/DeletedBy’a yazılan değer IAuditUserContext.UserId’den gelir:
Guid, Guid? değil): HTTP context’i olmayan akışlarda (background job, seeder, design-time) implementasyon SystemActor.Id döner. Yani audit kolonları asla boş kalmaz.
Design-time’da kullanılan no-op implementasyon:
Neden OnConfiguring’de eklenir?
AuditInterceptor scoped’tur — her request’te taze bir IAuditUserContext alması gerekir (güncel kullanıcı kimliği). Bu yüzden interceptor AddDbContext’in options builder’ına eklenmez; DbContext constructor’ı üzerinden inject edilip OnConfiguring’de eklenir:
Akış özeti
İlgili
Soft Delete
Deleted → Modified dönüşümü ve global query filter.
DbContext & Repository
SaveEntitiesAsync ve interceptor’ın çağrı sırası.
Migrations
Design-time NoAuditUserContext kullanımı.
Data Genel Bakış
Katman rolü ve SaveChanges akışı.