I'm using this code block to save Audit information to a Detail table. During this save, I need to get the PK from the AuditLog table record that was just saved so I can add the Detail record.
Audit.Core.Configuration.AddCustomAction(ActionType.OnEventSaved, scope =>
{
auditService.ConfigureAuditDetail(scope);
});
Since I only have scope available I am unable to locate the AuditLog entity except by a lookup against the context. Is this safe or could another record be saved before I get the right PK.
ctx.AuditLog.OrderByDescending(x => x.Id).FirstOrDefault().Id;
Is there any way to do this better?
public void ConfigureAuditDetail(AuditScope scope)
{
var efEvent = (scope.Event as AuditEventEntityFramework)?.EntityFrameworkEvent;
List<EventEntryChange> currentChanges = new List<EventEntryChange>();
var ctx = efEvent.GetDbContext() as DbContext;
var auditLogId = ctx.AuditLog.OrderByDescending(x => x.Id).FirstOrDefault().Id;
}
If you map your audit tables like this, so AuditLog
have a collection of AuditLogDetails
:
public class AuditLog
{
public int Id { get; set; }
public ICollection<AuditLogDetail> Details { get; set; }
public string Table { get; set; }
public string Action { get; set; }
}
public class AuditLogDetail
{
public int Id { get; set; }
public int AuditLogId { get; set; }
public string Column { get; set; }
public string Value { get; set; }
}
Then you can specify the mapping and the action for Audit EF like this:
Audit.Core.Configuration.Setup()
.UseEntityFramework(ef => ef
.UseDbContext<MyContext>()
.AuditTypeMapper(t => typeof(AuditLog))
.AuditEntityAction<AuditLog>((auditEvent, entry, auditLog) =>
{
auditLog.Table = entry.Table;
auditLog.Action = entry.Action;
auditLog.Details = entry.ColumnValues.Select(c => new AuditLogDetail()
{
Column = c.Key,
Value = c.Value.ToString()
}).ToList();
})
.IgnoreMatchedProperties());
So the audit entities are saved on the same transaction.