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”.
31 March 2016 at 0:44
Nice implementation. I think you should return base.SaveChanges(); though instead of return 1;
LikeLiked by 1 person
31 March 2016 at 8:15
yes, good idea too. I done this to manage the error in the catch branch, but maybe it’s better your idea, more clean!
LikeLike
20 September 2018 at 9:39
How to get the navigation property values in this case?
LikeLike
1 October 2018 at 8:04
Good question, unfortunetely I don’t know, do you have found something about this?
LikeLike
19 June 2019 at 7:17
Is it possible to ignore some entity and properties in the entity for being logged?
I thought creating new attribute IgnoreLoggingAttribute will help but it does not work for database first approach since EDMX and the Entity.cs was auto generated.
LikeLike