Skip to main content
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 sync SaveChanges yakalanır; ikisi de aynı ApplyAuditFields metodunu çağırır:

ApplyAuditFields

Her EntityBase entry’sinin state’ine göre ilgili alanlar set edilir:
DeletedModified dönüşümü soft-delete’in kalbidir: EF Core DELETE SQL’i yerine UPDATE üretir. Detaylar Soft Delete sayfasında.
Tüm zaman damgaları 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:
Bilinçli olarak nullable değil (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:
Scoped bir interceptor’ı AddDbContext options’a (singleton internal service provider) eklemek EF Core’un internal service provider cache’ini bozar ve scoped bağımlılığı doğru çözemez. OnConfiguring yolu bu sorunu aşar; DbContext’in iki constructor’ı (parametresiz design-time + DI runtime) bunun için vardır.

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ışı.