Question

I'm building some sort of an auditing behavior in an MVC3 app with EF, and I've tried several approaches, trying to avoid high impacts on the code, and, of course, trying to avoid as much extra code as I can, since the application is at 35-ish % done.

Audit object looks like this:

  • AuditId
  • UserId
  • OperationId
  • ModuleId
  • Timestamp
  • Payload
  • < Module >
  • < Operation >
  • < User >

The idea goes as follows:

I've created a partial class to hide the SaveChanges() and override SaveChanges(SaveOptions).

Then I've created two more overloads of the same method to receive my entity as a parameter and/or not a SaveOptions enum parameter.

The new SaveChanges() besides the obvious, sets the properties of my Audit entity, but the problem takes place here: I need a User, Module and an Operation.

My current solution to solve this is the following:

  • I've declared an Audit object at the constructor class level.
  • In the controller's constructor I set the User to my Audit object.
  • In each method I set the Operation as needed.
  • In the save changes I process the payload (an xml in my case) from the ObjectStateManager.

I'm very skeptic about this approach, it seems to be a little intrusive to my code. I've read lots of posts here in SO, but none of them helped me to improve this approach nor decide to change it. So please avoid linking things I've probably already read.

Was it helpful?

Solution

Another option is to decorate your database entities you wish to audit with a custom attribute. Check for the attribute during SaveChanges. For the module and operation fields, you can capture the stack trace at that time - find the calling controller and action from that. This would help keep your controllers cleaner.

I do audits at a column level, not obejct. Typically I only care about a few columns, not the entire thing. For reference, here's my base DbContext. I subscribe to the the ObjectContext.SavingChanges event, check everything marked as modified, and then for any properties with a custom [Audit] attribute. This could easily be expanded to also check for deletions.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top