This is the fourth and final 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
Hooking up the NHibernate IInterceptor
Now that we have written our IInterceptor, implemented as the AuditInterceptor class, we need to tell NHibernate to use it. This part will vary depending on how NHibernate is exposed to your application, but the basic idea is that when you open a session (using OpenSession() on your NHibernate session factory) you will pass along the interceptor as a parameter. If you have no interceptor, you can just call OpenSession().
Extending the NHibernate Session Manager
Our session manager class follows loosely with the thread-safe, lazy singleton patterned NHibernateSessionManager described in the NHibernate Best Practices Article. Adding hooks for a persistent interceptor was pretty easy – first I wrote a method for registering an interceptor:
This just sets a local static IInterceptor property called _registeredInterceptor. This is used whenever opening a session, as follows:
So once the IInterceptor is registered, all future calls to GetSession() will open a session using that interceptor (of course you could null it out again later, though I am not sure why you would want to).
Registering the Interceptor
On Application_Start in the global.asax file I call into the NHibernateSessionManager’s RegisterInterceptor method (seen above). The interceptor I want to register will be resolved by Castle Windsor through IoC/DI.
To tell Castle Windsor to use the AuditInterceptor, we add the following line to the IoC container registration:
Trying It Out
We are going to add a new “project” instance to our database. Basically in the code ASP.NET MVC creates a new Project instance with a Name property set, and makes sure it is Active by default. The code is kind of beside the point but I’ll post it anyway just make clear how transparent this interceptor is:
Let’s see (using NH Profiler) what happened to the database:
Perfect! We have two Insert Into statements wrapped in a transaction. The first statement saves the Project (I didn’t show it, but it is a simple Insert Into Projects with name = “NewProject”), and then second statement saves the audit record. You can see in the Details tab below that the record shows a Project was created by ‘srkirkland’ and saves the exact time of the action.
An update an delete look pretty much the same – here’s a quick screenshot of an update record being audited:
Ok – everything looks good. In the last four posts we have created a fully transparent auditing solution for recording all create/update/delete actions without our application. Pretty powerful stuff!