0

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 :

  1. Each time I insert a new entry in my table (using DbContext.[Model].Add(entry))

  2. 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 ?

Glad
  • 147
  • 1
  • 11
  • Which part that doesn't work? _When asking a question about a problem caused by your code, you will get much better answers if you provide code people can use to reproduce the problem. That code should be [Minimal, Complete and Verifiable](http://stackoverflow.com/help/mcve)_ – Yuliam Chandra Jul 31 '14 at 08:32
  • Actually...I am not even sure that what I have tried are the correct ways of achieving this specific logging action. – Glad Jul 31 '14 at 08:39
  • you used database first ? – Yuliam Chandra Jul 31 '14 at 08:40
  • No, Code First migrations. – Glad Jul 31 '14 at 08:41
  • do you have an interface / base class for all entities and the interface / base class has 2 properties of user and date? – Yuliam Chandra Jul 31 '14 at 08:43
  • Yes. All my entity classes inherits the logging columns from another class, which only has those 2 properties. – Glad Jul 31 '14 at 08:45
  • then you just need to extract all entities from ChangeTracker with that interface, then each entity fill the property – Yuliam Chandra Jul 31 '14 at 08:46
  • Hum, I am not very familiar with this. Could you please develop this in an answer to my question and not a comment ? So I could validate it if it works properly. – Glad Jul 31 '14 at 08:52

1 Answers1

0

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; }
}
Yuliam Chandra
  • 14,494
  • 12
  • 52
  • 67