ASP MVC / EF6 - Automatic logging
-
21-12-2019 - |
Question
Every table of my database has got 2 columns at the end, which allows logging (User who made the action, and Date of the action). EDIT : I use Code-First migrations.
So I would like those two logging columns to be filled automatically :
Each time I insert a new entry in my table (using DbContext.[Model].Add(entry))
OR each time I do a DbContext.SaveChanges() action
I have considered overriding the DbContext.SaveChanges() method, but it didn't work out...
I have also tried overriding the DbSet Add() method, to do the log filling action there. For that I have created a CustomDbSet class which inherits from DbSet :
public class CustomDbSet<TEntity> : DbSet<TEntity> where TEntity : class
{
public TEntity Add(TEntity entity)
{
//Do logging action here
return base.Add(entity);
}
}
But this didn't make it neither.
EDIT : What happens with this CustomDbSet is that any DbContext.[Model] returns null, now (instead of being filled with the content of the database table)
I already have the extension method which will do the logging action, but I don't know where to put it so logging would become an "automatic" action..
public static void EntityLogCreate<T>(this T model, string userName) where T : LogColumns
{
model.Create_User = userName;
model.Create_Date = DateTime.Now;
}
Any idea to achieve that ?
Solution
Here is an example how to do it.
public class AppContext : DbContext
{
public DbSet<Item> Items { get; set; }
public override int SaveChanges()
{
int actionById = 1; // Need a way to get the user who does the action.
DateTime actionDate = DateTime.Now;
var entries = ChangeTracker.Entries<IAuditLog>();
foreach (var entry in entries)
{
if (entry.State != EntityState.Added && entry.State != EntityState.Modified) continue;
// Only added and modified entries.
entry.Entity.ActionById = actionById;
entry.Entity.ActionDate = actionDate;
}
return base.SaveChanges();
}
}
public interface IAuditLog
{
int? ActionById { get; set; }
DateTime? ActionDate { get; set; }
}
public class Item : IAuditLog
{
public int Id { get; set; }
public string Name { get; set; }
public int? ActionById { get; set; }
public DateTime? ActionDate { get; set; }
}