Skip to content

Instantly share code, notes, and snippets.

@garima2510
Last active July 4, 2025 11:02
Show Gist options
  • Select an option

  • Save garima2510/3da164fd96a8cab0e16e04fb79a08bd4 to your computer and use it in GitHub Desktop.

Select an option

Save garima2510/3da164fd96a8cab0e16e04fb79a08bd4 to your computer and use it in GitHub Desktop.
Partial class to override SaveChanges of DbContext and use it for creating audit trail
public partial class CustomDbContext: DbContext
{
public override int SaveChanges()
{
// Get all Added/Deleted/Modified entities (not Unmodified or Detached)
//you can get updated and deleted in same collection. I am doing so for ease of purpose
//getting added entries in different collection to fetch their generated ids and then log them
var addedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Added).ToList();
var updatedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).ToList();
var deletedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted).ToList();
foreach (var entry in updatedEntries)
{
ApplyAuditLog(entry);
}
foreach (var entry in deletedEntries)
{
ApplyAuditLog(entry);
}
int changes = base.SaveChanges();
foreach (var entry in addedEntries)
{
ApplyAuditLog(entry);
}
base.SaveChanges();
return changes;
}
/// <summary>
/// code to enter values in audit table
/// </summary>
/// <param name="entry"></param>
/// <param name="auditType"></param>
private void ApplyAuditLog(DbEntityEntry entry)
{
//get table name of entry
string tableName = GetTableName(entry);
//exlude audit table from getting audited
if (!tableName.Equals("Audit", StringComparison.OrdinalIgnoreCase))
{
//code to get primary key (id) of object which is updated
var objectStateEntry = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager.GetObjectStateEntry(entry.Entity);
int primaryKeyOfEntity = (int)objectStateEntry.EntityKey.EntityKeyValues[0].Value;
DateTime currentDateTime = DateTime.Now;
//code to convert the updated/added/deleted entry to json using newtonsoft json nuget package
string serializedJson = JsonConvert.SerializeObject(entry.CurrentValues.ToObject(), Formatting.Indented, new JsonSerializerSettings
{
//below code ignores the circular references. Main reason XML is not used as this was so wasy in JSON
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
Audit auditTrail = new Audit()
{
TimeStamp = currentDateTime,
AuthenticatedUser = {/* code to log authenticated user */ },
LinkedID = primaryKeyOfEntity,
AuditType = {/*create/update/delete/or read. Write your own logic here */ },
TableName = tableName,
NewValue = serializedJson
};
//you can write code here to generated checksum using algo like SHA1, MD5 and then update it in audit trail
//string checksumValue = GetChecksumValueFromTrail(auditTrail);
//write code to add entry in audit table here like below
//Audit.Add(auditTrail);
}
}
/// <summary>
/// method to fetch table name of updated entity
/// </summary>
/// <param name="dbEntityEntry"></param>
/// <returns></returns>
private string GetTableName(DbEntityEntry dbEntityEntry)
{
ObjectContext objectContext = ((IObjectContextAdapter)this).ObjectContext;
Type entityType = dbEntityEntry.Entity.GetType();
if (entityType.BaseType != null && entityType.Namespace == "System.Data.Entity.DynamicProxies")
entityType = entityType.BaseType;
string entityTypeName = entityType.Name;
EntityContainer container =
objectContext.MetadataWorkspace.GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace);
string entitySetName = (from meta in container.BaseEntitySets
where meta.ElementType.Name == entityTypeName
select meta.Name).First();
return entitySetName;
}
}
@vinaghost
Copy link

hello, i know this was 5 years ago but can I ask why you base.SaveChanges(); twice?

@garima2510
Copy link
Author

Hello, As far as I remember, I wanted to get the number of rows modified/deleted for some logic in the code. Hence called it twice to keep added rows and modified rows separate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment