Search code examples
entity-framework-core.net-7.0

Is there anyway to add multiple SaveChangesInterceptor


I already have a SaveChangesInterceptor which is responsible for updating Audit Properties like Created date, CreatedBy, LastModified and LastModifiedBy. here is the Auditable Code snippet:

public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)
{
    UpdateEntities(eventData.Context);

    return base.SavingChangesAsync(eventData, result, cancellationToken);
}

public void UpdateEntities(DbContext? context)
{
    if (context == null) return;

    foreach (var entry in context.ChangeTracker.Entries<BaseAuditableEntity>())
    {
        if (entry.State == EntityState.Added)
        {
            entry.Entity.Created = _dateTime.Now;
            entry.Entity.CreatedBy = _currentUserService.UserId;
        }

        if (entry.State == EntityState.Added || entry.State == EntityState.Modified || entry.HasChangedOwnedEntities())
        {
            entry.Entity.LastModified = _dateTime.Now;
            entry.Entity.LastModifiedBy = _currentUserService.UserId;
        }
    }
}

I want to add another SaveChangesInterceptor which will be responsible to convert hard delete to soft delete by setting IsDeleted Property to true here is the soft delete Code snippet:

public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)
{
    SoftDeleteEntities(eventData.Context);

    return base.SavingChangesAsync(eventData, result, cancellationToken);
}
public void SoftDeleteEntities(DbContext? context)
{
    if (context == null) return;

    var deletedEntries = context.ChangeTracker
                               .Entries<BaseAuditableSoftDeletableEntity>()
                               .Where(entry => entry.State == EntityState.Deleted)
                               .ToList();

    foreach (var entry in deletedEntries)
    {
        entry.State = EntityState.Modified;
        entry.Entity.IsDeleted = true;
    }
}

and here is the dependency injection

services.AddScoped<AuditableEntitySaveChangesInterceptor>();
services.AddScoped<SoftDeletableEntitySaveChangesInterceptor>();

the execution enters the Auditable Interceptor but not goes through Soft Delete Interceptor


Solution

  • I registered the Interceptor to DbContext according to @Svyatoslav comment and it works, the code will be like the following

    private readonly AuditableEntitySaveChangesInterceptor _auditableEntitySaveChangesInterceptor;
    private readonly SoftDeletableEntitySaveChangesInterceptor _softDeletableEntitySaveChangesInterceptor;
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
       optionsBuilder.AddInterceptors(_auditableEntitySaveChangesInterceptor);
       optionsBuilder.AddInterceptors(_softDeletableEntitySaveChangesInterceptor);
    }