NHibernate Event Listener Registration With Fluent NHibernate

I’m a huge fan of NHibernate. It has excellent documentation and just makes the whole job of getting things into and out of the database much more enjoyable.  There is a whole series of posts on NHibernate from one of the committers, Ayende.  When Fluent NHibernate (FNH) came out, it was like butter on sliced bread.  FNH makes it even easier to use NHibernate.

Ayende had a post a while back on how to use Event Listeners.  That helped me to get to event listeners set up.

Event Listeners

namespace somethingimportant.we.hope.infrastructure.app.auditing
{
    using System;
    using System.Security.Principal;
    using System.Web;
    using domain;
    using NHibernate.Event;
    using NHibernate.Persister.Entity;
 
    public class AuditEventListener : IPreInsertEventListener, IPreUpdateEventListener
    {
        public string get_identity()
        {
            string identity_of_updater = WindowsIdentity.GetCurrent().Name;
 
        if (HttpContext.Current != null)
            {
                try
                {
                    identity_of_updater = HttpContext.Current.User.Identity.Name;
                }
                catch
                {
                    //move on
                }
            }
 
            return identity_of_updater;
        }
 
        //http://ayende.com/Blog/archive/2009/04/29/nhibernate-ipreupdateeventlistener-amp-ipreinserteventlistener.aspx
        public bool OnPreInsert(PreInsertEvent eventItem)
        {
            Auditable audit = eventItem.Entity as Auditable;
            if (audit == null)
            {
                return false;
            }
 
            DateTime? entered_date = DateTime.Now;
            DateTime? modified_date = DateTime.Now;
            string identity_of_updater = get_identity();
 
            store(eventItem.Persister, eventItem.State, "entered_date", entered_date);
            store(eventItem.Persister, eventItem.State, "modified_date", modified_date);
            store(eventItem.Persister, eventItem.State, "updating_user", identity_of_updater);
            audit.entered_date = entered_date;
            audit.modified_date = modified_date;
            audit.updating_user = identity_of_updater;
 
            return false;
        }
 
        public bool OnPreUpdate(PreUpdateEvent eventItem)
        {
            Auditable audit = eventItem.Entity as Auditable;
            if (audit == null)
            {
                return false;
            }
 
            DateTime? modified_date = DateTime.Now;
            string identity_of_updater = get_identity();
 
            store(eventItem.Persister, eventItem.State, "modified_date", modified_date);
            store(eventItem.Persister, eventItem.State, "updating_user", identity_of_updater);
            audit.modified_date = modified_date;
            audit.updating_user = identity_of_updater;
 
            //insert auditing object here
 
            return false;
        }
 
        public void store(IEntityPersister persister, object[] state, string property_name, object value)
        {
            int index = Array.IndexOf(persister.PropertyNames, property_name);
            if (index == -1)
            {
                return;
            }
            state[index] = value;
        }
    }
}
Great! But now I need to register my event listeners.So I go searching some on the interwebs. And I come across this. Ayende talks about how to registration in the configuration file in a later post, but with FNH, I register in code.  Hmmm… back to the interwebs…
Then I came across Adam Aldrich’s post on how to register the listeners in code. This is from his post on registration:
NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
cfg.EventListeners.PreUpdateEventListeners = 
    new IPreUpdateEventListener[] {new AuditEventListener()};
cfg.EventListeners.PreInsertEventListeners =
    new IPreInsertEventListener[] { new AuditEventListener() };
_sessionFactory = cfg.BuildSessionFactory();
Just what I was looking for! Code registration. But how do I use FNH to set that up?  That’s where some nice detective work and a fluent interface come in.
Fluent NHibernate Registration of Event Listeners
private void build_factory()
{
    if (nhibernate_session_factory == null)
    {
        nhibernate_session_factory = Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2005
                .ConnectionString(c => 
                    c.FromConnectionStringWithKey("db")))
            .Mappings(m => 
                m.FluentMappings.AddFromAssemblyOf<VideoMapping>())
            .ExposeConfiguration(cfg => {
                        cfg.EventListeners.PreInsertEventListeners = 
                            new IPreInsertEventListener[] {new AuditEventListener()};
                        cfg.EventListeners.PreUpdateEventListeners = 
                            new IPreUpdateEventListener[] {new AuditEventListener()};
                        })
            .BuildSessionFactory();
    }
}

 

This same thing can be accomplished with VB.NET by making a call to a method (I’ve done that as well). With it’s discoverability, FNH makes it so easy to figure things out sometimes. :D

 

 

kick it on DotNetKicks.com Shout it

Print | posted @ Wednesday, November 18, 2009 1:04 AM

Comments on this entry:

Gravatar # re: NHibernate Event Listener Registration With Fluent NHibernate
by Darrell Mozingo at 11/18/2009 2:05 AM

Another option, inside your ExposeConfiguration delegate:

cfg.SetListener(ListenerType.PreInsert, new AuditEventListener());
cfg.SetListener(ListenerType.PreUpdate, new AuditEventListener());

Not sure what differences, if any, there are, but it does look a little cleaner. Nice post!
Gravatar # re: NHibernate Event Listener Registration With Fluent NHibernate
by Harry M at 11/18/2009 2:21 AM

Well pointed out Darrell, theres a WHOLE bunch of stuff you could already do without need FNH that gets ignored for some reason.
Gravatar # re: NHibernate Event Listener Registration With Fluent NHibernate
by Robz at 11/18/2009 4:27 AM

@Darrell: Ooh. I like that better. It's much cleaner.

@Harry: The expose configuration gets you back to NHibernate configuration. This post isn't about whether you should use FNH or not. Just that if you do, this is how you get Listeners set up.
Comments have been closed on this topic.