Entity Framework is very powerful. It takes care of the dirty jobs and it makes your programmer’s life easier. A very useful feature you can use is override the saveChanges method, for example, to audit/track the changes made.

In my case, I was working on a database, where some tables have the columns “user_mod” and “date_mod” for sign who and when made some mods and the same with “data_new” and “user_new”, to track who and when inserted that row.

And I was wondering: is there a way to centralize this and make this data inserted automatically, where I create the instance of dbContext?

I have seen some of these, but there is a problem: all of these, require some code in my model. But I don’t want to write in my model, because if I have to change it, I will lost the mods. Is it possible use an audit trail for EF6 without writing in the model file(s)? How?

So, my attempt was to override the saveChanges. And this is how I made it.

public partial class Entities : DbContext
{
    public override int SaveChanges()
    {
        var addedAuditedEntities = Entities.dbContext.ChangeTracker.Entries()
                .Where(p => p.State == EntityState.Added)
                .Select(p => p.Entity);
        var modifiedAuditedEntities = Entities.dbContext.ChangeTracker.Entries()
              .Where(p => p.State == EntityState.Modified)
              .Select(p => p.Entity);
        var deletedAuditedEntities = Entities.dbContext.ChangeTracker.Entries()
                .Where(p => p.State == EntityState.Deleted)
                .Select(p => p.Entity);
        var now = DateTime.Now;

        using (var ctx = new Entities(GetConnectionString("Model")))
        {
            foreach (var added in addedAuditedEntities)
            {
                if (added.GetType() == typeof(Table1))
                {
                    var i = (Table1)added;
                    i.DATA_INS = now;
                    i.USER_INS = UserName;
                }
                else if (added.GetType() == typeof(Table2))
                {
                    ...
                }
                else ...

            foreach (var modified in modifiedAuditedEntities)
                {
                    if (modified is Table1)
                    {
                        var i = (Table1)modified;
                        i.DATA_MOD = now;
                        i.USER_MOD = UserName;
                    }
                    else if (modified is Table2)
                    {
                    ...
                }
                else ...
            try
            {
                {
                    base.SaveChanges();
                    return 1;
                }
            }
            catch (Exception e)
            {
                //manage error here
                return -1;
            }
        }
}

In this way, when you’ll call the saveChanges method, you’ll this override, managing the auditing like you have choosen here.

NOTE: this is only a custom use of the saveChages override. Limits are only in your head! For example, you can use this function to implement more detailed audit or also a sort of custom trigger managed with Entity Framework. You can also loop over the deleted records of some tables and track this operation writing it on a “DeletionArchive”.

Advertisements