Audit.Net: Audit Record Not Rolling Back When saving master record throws DbUpdateException

246 Views Asked by At

I have been using Audit.EntityFramework.Core v14.6.3 in my .Net Core v2.2 Web API.

When I update a table record, it threw dbUpdateException error due to a check constraint conflict in the table. While the master record did not save into the db as what I have expected, the audit record went through and inserted into the audit table.

I'm curious why the audit record did not rollback together with the master record. Is there additional implementation/configuration needs to be done?

I have mapped all master tables their respective audit table:

var optionsBuilder = new Microsoft.EntityFrameworkCore.DbContextOptionsBuilder<DGAuditDBContext>();           optionsBuilder.UseSqlServer(EncryptionManager.DecryptKey(Microsoft.Extensions.Configuration.ConfigurationExtensions.GetConnectionString(this._configuration, "localhost")));
                    Audit.Core.Configuration.Setup()
                        .UseEntityFramework(ef => ef
                           .UseDbContext<DGAuditDBContext>(optionsBuilder.Options)
                           .AuditTypeExplicitMapper(m => m
                              .Map<AdmissionType, Audit_AdmissionType>()
                              .AuditEntityAction((evt, entry, auditEntity) =>
                               {
                                   ((dynamic)auditEntity).AuditDate = DateTime.UtcNow;
                                   ((dynamic)auditEntity).UserID = user_name;
                                   ((dynamic)auditEntity).AuditAction = entry.Action;
                               })
                           )
                        );

Configuration in my dbcontext:

public class DGDBContext : IdentityDbContext<AppUser> {

        private static DbContextHelper _helper = new DbContextHelper ();
        private readonly IAuditDbContext _auditContext;
        protected override void OnConfiguring (DbContextOptionsBuilder optionsBuilder) {

            optionsBuilder.EnableSensitiveDataLogging ();

            base.OnConfiguring (optionsBuilder);
        }

        public DGDBContext (DbContextOptions<DGDBContext> options) : base (options) {
        
                    _auditContext = new DefaultAuditContext (this);
                    _helper.SetConfig (_auditContext);
                }
                public override int SaveChanges () {
                    return _helper.SaveChanges (_auditContext, () => base.SaveChanges ());
                }
        
                public override async Task<int> SaveChangesAsync (CancellationToken cancellationToken = default (CancellationToken)) {
                    return await _helper.SaveChangesAsync (_auditContext, () => base.SaveChangesAsync (cancellationToken));
                }
        
        public DbSet<AdmissionType> AdmissionType{ get; set; }
        public DbSet<Audit_AdmissionType> Audit_AdmissionType{ get; set; }
}

Any idea/help would be appreciated.

1

There are 1 best solutions below

0
On BEST ANSWER

The Audit.EntityFramework helper/context will trigger audit events regardless of the result of the SaveChanges operation. So by default it will try to save the failed events.

But you can change your AuditEntityAction to return a boolean to indicate whether the audit should be included or discarded, and make it dependant on the Success field of the EF event:

    .AuditEntityAction((ev, entry, auditEntity) =>
    {
      // ...

      return (ev as AuditEventEntityFramework).EntityFrameworkEvent.Success;
    })