/// <summary> /// Adds entries to the audit models and returns the RecentUpdateDb. As SaveChanges call is required to commit the changes from the caller. /// </summary> /// <param name="changeTracker"></param> /// <param name="userId"></param> /// <returns></returns> public AuditModelContext AuditChanges(DbChangeTracker changeTracker, string userId) { //Record changes into the Audit DB. AuditModelContext recentUpdateDb = new AuditModelContext(); //Create an exclusion list for audit string[] excludedFromAudit = new string[] { "ModifiedById", "Modified", "CreatedById", "Created" }; IEnumerable <DbEntityEntry> auditEntries = changeTracker.Entries().Where(x => x.Entity is BaseBaseModel && (x.State == EntityState.Modified)); foreach (DbEntityEntry entry in auditEntries) { if (entry.GetType().GetCustomAttribute(typeof(NoAuditAttribute)) == null) { var currentValues = entry.CurrentValues; var databaseValues = entry.GetDatabaseValues(); if (currentValues != null) { foreach (string propertyName in currentValues.PropertyNames.Except(excludedFromAudit)) { if (!string.IsNullOrWhiteSpace(propertyName)) { var propertyValue = databaseValues.GetValue <object>(propertyName); //Use nullPlaceholder for equals Operation. object originalValue = propertyValue; object currentValue = currentValues[propertyName]; //Audit changes and non-ReadOnly Fields. if (entry.Entity.GetType().GetProperty(propertyName).GetCustomAttribute(typeof(TFOF.Areas.Core.Attributes.ReadOnlyAttribute)) == null) { recentUpdateDb.Add( ObjectContext.GetObjectType(entry.Entity.GetType()).Name, ((BaseBaseModel)entry.Entity).GetPrimaryKey(), propertyName, originalValue, currentValue, userId ); } } } } } } return(recentUpdateDb); }