I'm looking at using Entity Framework 6.1.1 with SQL Server 2008 R2.
Currently I'm creating my models and database using the code-first EF feature. My basic use-case is to create a journal of all changes to a particular entity (ID
is the key column) to help auditors track all changes made and by whom. e.g:
|ID|Version|Created Date|Created By|Modified Date|Modified By|Modify Action| ... (rest of entity fields)
-------------------------------------------------------------------------------------------------------
| 4| 12 | 12-Mar-14 | tom | 20-Feb-15 | jack | Update |
| 4| 11 | 12-Mar-14 | tom | 14-Feb-15 | jill | Update |
| 4| 1 | 12-Mar-14 | tom | 12-Mar-14 | tom | Create |
Does Entity Framework support this type of database scheme? If so, how can I set my models/solution up to facilitate this?
The other alternative I have is by intercepting all calls to the SaveChanges()
method on the DbContext
and log all database changes into a separate Audit
table, but this might make retrieving information more challenging.
Any help on creating audit trails with SQL Server and EF 6 would be greately appreciated.
You could look at Entity Framework Extended. It has audit functionality that I have used to log all changes to entities to XML. From the documentation:
UPDATE:
Entity Framework Extended is no longer supported since 2015. Please refer to Entity Framework Plus for this feature.
I would say this is a good candidate for the event sourcing pattern mentioned in a DDD architecture. You never change your entity table but always inserting.
In that way, when you need an specific version you just re-play all events and apply them to the entity from version 0 to the version you are looking for. Scalability can be solved with entity snapshots.
Second approach is also valid.
Reference: http://microservices.io/patterns/data/event-sourcing.html
I have used the 2nd approach you mention, by overloading the dbContext SaveChanges() method:
So if I want to log a particular entity, I just call the overloaded SaveChanges & pass in a UserId:
I also have a custom
DoNotLog
attribute which I use to decorate the entity properties that I don't want to log. Without this, the logging could generate a huge amount of data, as each entity modification equals one db entry.The
GetAuditRecordsForChange
method does the checking for anyDoNotLog
properties and returns aList<AuditLog>
which gets saved in the AuditLogs table: