Entity Framework 6: audit/track changes
If using EF6's DbContext
you can use ChangeTracker
in SaveChanges
override to find added/modified entities of custom type, for example IAuditedEntity.
public interface IAuditedEntity {
string CreatedBy { get; set; }
DateTime CreatedAt { get; set; }
string LastModifiedBy { get; set; }
DateTime LastModifiedAt { get; set; }
}
public override int SaveChanges() {
var addedAuditedEntities = ChangeTracker.Entries<IAuditedEntity>()
.Where(p => p.State == EntityState.Added)
.Select(p => p.Entity);
var modifiedAuditedEntities = ChangeTracker.Entries<IAuditedEntity>()
.Where(p => p.State == EntityState.Modified)
.Select(p => p.Entity);
var now = DateTime.UtcNow;
foreach (var added in addedAuditedEntities) {
added.CreatedAt = now;
added.LastModifiedAt = now;
}
foreach (var modified in modifiedAuditedEntities) {
modified.LastModifiedAt = now;
}
return base.SaveChanges();
}
EF 6 DB First Audit Logs
To achieve this, I did not use any utility as my requirements were bit different. Finally I went ahead with overriding the SaveChanges
method of DbContext
used by EF. Also used Newtonsoft JSON library to convert whole updated object to JSON and save it.
To get complete code, check this link - How to audit MVC app which used EF DB first approach
EF6 Change tracking
You're not overriding SaveChanges()
. You're creating a new wrapper class, and creating a SaveChanges method, and then trying to call SaveChanges()
of your wrapped context. That's something totally different from overriding SaveChanges()
. If you read the documentation for AutoDetectChangesEnabled You will find that it says this:
Gets or sets a value indicating whether the DetectChanges() method is called automatically by methods of DbContext and related classes. The default value is true.
So what it means is that DetectChanges()
gets called when you call methods of the DbContext
, which is something you are not doing. You ARE calling a method of the ObjectContext
, which is not part of the DbContext
(DbContext
inherits from it), thus calling this method wouldn't trigger a DetectChanges()
call.
Implementing Audit Log / Change History with MVC & Entity Framework
IF you are using EF 4 you can subscribe to the SavingChanges
event.
Since Entities
is a partial class you can add additional functionality in a separate file. So create a new file named Entities
and there implement the partial method OnContextCreated
to hook up the event
public partial class Entities
{
partial void OnContextCreated()
{
SavingChanges += OnSavingChanges;
}
void OnSavingChanges(object sender, EventArgs e)
{
var modifiedEntities = ObjectStateManager.GetObjectStateEntries(EntityState.Modified);
foreach (var entry in modifiedEntities)
{
var modifiedProps = ObjectStateManager.GetObjectStateEntry(entry.EntityKey).GetModifiedProperties();
var currentValues = ObjectStateManager.GetObjectStateEntry(entry.EntityKey).CurrentValues;
foreach (var propName in modifiedProps)
{
var newValue = currentValues[propName];
//log changes
}
}
}
}
If you are using EF 4.1 you can go through this article to extract changes
AzureSQL and EF 6 Auditing Records
To track "what has happened in the system at any point in time" you can use a feature that is built in to Azure SQL, Temporal tables. "Temporal Tables are a new programmability feature of Azure SQL Database that allows you to track and analyze the full history of changes in your data, without the need for custom coding". See:
https://learn.microsoft.com/en-us/azure/sql-database/sql-database-temporal-tables
Related Topics
When to Use Ilist and When to Use List
Weak Event Handler Model for Use with Lambdas
How to Capture Screen to Be Video Using C# .Net
Run Code Once Before and After All Tests in Xunit.Net
How to Conditionally Compile My C# for Mono VS. Microsoft .Net
Convert from SQLdatareader to JSON
Best Method to Obfuscate or Secure .Net Assemblies
How to Show the Sum of in a Datagridview Column
How to Test If a Type Is Anonymous
Get Value of C# Dynamic Property via String
Why Does Path.Combine Not Properly Concatenate Filenames That Start with Path.Directoryseparatorchar
Asp .Net MVC Disable Client Side Validation at Per-Field Level
How to Read the Data in a Wav File to an Array