Thursday, September 03, 2009 11:24 AM srkirkland

Simple Auditing using an NHibernate IInterceptor (part 1)

This is the beginning 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 Audit Class

The Audit class will inherit from a base DomainObject<> which basically provides an Id property for all objects and helper methods for validation and transient checks (this is pretty common architecture when using NHibernate).  I’m using EntLib validation on the class and to satisfy a particular requirement I am going to set the action type to C/U/D depending on the action.  Here’s the code:

   1: public class Audit : DomainObject<Audit,Guid>
   2: {
   3:     [RequiredValidator]
   4:     [StringLengthValidator(50)]
   5:     public virtual string ObjectName { get; set; }
   6:  
   7:     [IgnoreNulls]
   8:     [StringLengthValidator(50)]
   9:     public virtual string ObjectId { get; set; }
  10:  
  11:     [RequiredValidator]
  12:     [StringLengthValidator(1)]
  13:     public virtual string AuditActionTypeId { get; set; }
  14:  
  15:     [RequiredValidator]
  16:     [StringLengthValidator(256)]
  17:     public virtual string Username { get; set; }
  18:  
  19:     public virtual DateTime AuditDate { get; set; }
  20:  
  21:     public virtual void SetActionCode(AuditActionType auditActionType)
  22:     {
  23:         switch (auditActionType)
  24:         {
  25:             case AuditActionType.Create:
  26:                 AuditActionTypeId = "C";
  27:                 break;
  28:             case AuditActionType.Update:
  29:                 AuditActionTypeId = "U";
  30:                 break;
  31:             case AuditActionType.Delete:
  32:                 AuditActionTypeId = "D";
  33:                 break;
  34:             default:
  35:                 throw new ArgumentOutOfRangeException("auditActionType");
  36:         }
  37:     }
  38: }
  39:  
  40: public enum AuditActionType
  41: {
  42:     Create, Update, Delete
  43: }

Audit Repository Testing

Before I move on to creating the interceptor I am going to run a few tests against a SQLite repository to make sure the Audit class can save and validate properly.

   1: [TestMethod]
   2: public void ValidationAuditWithoutSettingActionCodeShouldFail()
   3: {
   4:     var audit = new Audit
   5:     {
   6:         AuditDate = DateTime.Now,
   7:         ObjectName = "ValidObject",
   8:         Username = "ValidUsername"
   9:     };
  10:  
  11:     var isValid = ValidateBusinessObject<Audit>.IsValid(audit);
  12:  
  13:     Assert.AreEqual(false, isValid, "An audit requires an action code");
  14: }
  15:  
  16: [TestMethod]
  17: public void ValidationBlankAuditShouldFail()
  18: {
  19:     var audit = new Audit();
  20:  
  21:     var isValid = ValidateBusinessObject<Audit>.IsValid(audit);
  22:  
  23:     Assert.AreEqual(false, isValid, "A blank audit should not be valid");
  24: }

And to test that saving works properly:

   1: [TestMethod]
   2: public void CanSaveCompleteAndValidAudit()
   3: {
   4:     var audit = new Audit
   5:                     {
   6:                         AuditDate = DateTime.Now,
   7:                         ObjectName = "ValidObject",
   8:                         ObjectId = "ValidId",
   9:                         Username = "ValidUsername"
  10:                     };
  11:     
  12:     audit.SetActionCode(AuditActionType.Update);
  13:  
  14:     using (var ts = new TransactionScope())
  15:     {
  16:         _auditRepository.EnsurePersistent(audit);
  17:  
  18:         ts.CommitTransaction();
  19:     }
  20:  
  21:     Assert.AreEqual(false, audit.IsTransient(), "Audit should have been saved");
  22: }
  23:  
  24: [TestMethod]
  25: public void CanSaveAuditWithoutObjectId()
  26: {
  27:     var audit = new Audit
  28:     {
  29:         AuditDate = DateTime.Now,
  30:         ObjectName = "ValidObject",
  31:         Username = "ValidUsername"
  32:     };
  33:  
  34:     audit.SetActionCode(AuditActionType.Update);
  35:  
  36:     using (var ts = new TransactionScope())
  37:     {
  38:         _auditRepository.EnsurePersistent(audit);
  39:  
  40:         ts.CommitTransaction();
  41:     }
  42:  
  43:     Assert.AreEqual(false, audit.IsTransient(), "Audit should have been saved");
  44: }

What Did This Accomplish?

Not much yet.  We have an audit class that is behaving how we want, and eventually we are going to use it to save audit records.  Next time we’ll create an IInterceptor which will hook into create/update/delete events in NHibernate.

Filed under: , ,

Comments

# Simple Auditing using an NHibernate IInterceptor (part 1) - Scott's Blog

Pingback from  Simple Auditing using an NHibernate IInterceptor (part 1) - Scott's Blog

# re: Simple Auditing using an NHibernate IInterceptor (part 1)

Thursday, September 03, 2009 3:44 PM by cool

cool - can't wait to see the rest

# Simple Auditing using an NHibernate IInterceptor (part 1) | I love .NET!

Pingback from  Simple Auditing using an NHibernate IInterceptor (part 1) | I love .NET!

# Twitter Trackbacks for Simple Auditing using an NHibernate IInterceptor (part 1) - Scott's Blog [asp.net] on Topsy.com

Pingback from  Twitter Trackbacks for                 Simple Auditing using an NHibernate IInterceptor (part 1) - Scott's Blog         [asp.net]        on Topsy.com

# Simple auditing using an NHibernate IInterceptor (Part 3)

Thursday, September 10, 2009 4:27 PM by Scott's Blog

This is the third post of a multi-part post series on writing simple auditing functionality for an ASP

# Simple auditing using an NHibernate IInterceptor (Part 3)

Thursday, September 10, 2009 4:39 PM by Scott's Blog

This is the third post of a multi-part post series on writing simple auditing functionality for an ASP

# Simple auditing using an NHibernate IInterceptor (Part 3) | I love .NET!

Pingback from  Simple auditing using an NHibernate IInterceptor (Part 3) | I love .NET!

# Simple auditing using an NHibernate IInterceptor (Part 4)

Tuesday, September 15, 2009 12:58 PM by Scott's Blog

This is the fourth and final post of a multi-part post series on writing simple auditing functionality

# Simple auditing using an NHibernate IInterceptor (Part 4) | I love .NET!

Pingback from  Simple auditing using an NHibernate IInterceptor (Part 4) | I love .NET!

# re: Simple Auditing using an NHibernate IInterceptor (part 1)

Monday, September 20, 2010 10:00 PM by Katherine Flouee

Nice post you got here. It would be great to read something more about that theme. The only thing this blog misses is a few photos of some gizmos.

Katherine Flouee

<a href="www.jammer-store.com/">mobile phone signal blocker</a>

Leave a Comment

(required) 
(required) 
(optional)
(required)