Simple auditing using an NHibernate IInterceptor (Part 3)

This is the third post of a multi-part post series on writing simple auditing functionality for an ASP.NET application using NHibernate.  The requirement was that every object modification event in the system should be logged by username and date.  Specifically I don’t need to know exactly which properties were changed (just that a user was updated by whom at what time), but if you do need to save the changed properties there are plenty of hooks to do that.

I’ll update this post with links to the next parts when they become available

The AuditObjectModification Method

In Part 2 we wrote a bunch of tests for the AuditObjectModification method in the AuditInterceptor.cs class.  This method currently just throws a NotImplementedException:

   1: public void AuditObjectModification(object entity, object id, AuditActionType auditActionType)
   2: {
   3:     throw new NotImplementedException();
   4: }

 

I won’t go through each test individually (just the first one as an example), but when writing this iteratively you might want to go through each test and get them to pass one at a time.

Satisfying the First Test

Let’s start making by sure that the first test – AuditObjectModificationSouldNotSaveAuditEntity – can pass by making sure we don’t save audit objects:

   1: public void AuditObjectModification(object entity, object id, AuditActionType auditActionType)
   2: {
   3:     if (entity is Audit) return;
   4: }

 

And after running the tests:

AuditInterceptorTestsFailing

And now the first test passes!

Implementing the Rest

All that is left is to create an instance of the Audit class, fill out some properties, and save it. My implementation is below:

   1: public void AuditObjectModification(object entity, object id, AuditActionType auditActionType)
   2: {
   3:     if (entity is Audit) return;
   4:  
   5:     var audit = new Audit
   6:     {
   7:         AuditDate = DateTime.Now,
   8:         ObjectName = entity.GetType().Name,
   9:         ObjectId = id == null ? null : id.ToString(),
  10:         Username = UserAuth.CurrentUserName
  11:     };
  12:  
  13:     audit.SetActionCode(auditActionType);
  14:  
  15:     AuditRepository.EnsurePersistent(audit);
  16: }

 

Now we rerun the tests:

AuditInterceptorTestsSuccess

Now that’s what I like to see!

Calling the AuditObjectModification method

No we need to call our newly implemented method from the empty overrides of the AuditInterceptor method:

   1: public override void OnDelete(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types)
   2: {
   3:     AuditObjectModification(entity, id, AuditActionType.Delete);
   4:  
   5:     base.OnDelete(entity, id, state, propertyNames, types);
   6: }
   7:  
   8: public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types)
   9: {
  10:     AuditObjectModification(entity, id, AuditActionType.Create);
  11:  
  12:     return base.OnSave(entity, id, state, propertyNames, types);
  13: }
  14:  
  15: public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types)
  16: {
  17:     AuditObjectModification(entity, id, AuditActionType.Update);
  18:  
  19:     return base.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
  20: }

And we are now finished with our Audit Interceptor!

Next time we’ll hook the interceptor into NHibernate and look at the fruits of our labor.

4 Comments

Comments have been disabled for this content.