Fluent NHibernate Rocks

At work, we are preparing to institute an “Innovation Idea of the Quarter” program.  I say “Innovation Idea” and not “Innovator” because the idea doesn’t necessarily need to end up being implemented for the person who came up with it to win.  I think this is great, because it really encourages people to think outside of the box from the way we normally develop, and not to just propose things they know for sure would be “safe” enough to actually go into the product.

As you can probably tell from the title of this post, I’ve already decided what my initial submission is going to be.  A few months back, when we were first floating the idea of the innovation program, I started trying to prototype using NHibernate in one of our smaller systems as a proof-of-concept.  I eventually got one of search pages working, but it took a lot of trial and error with the “hbm.xml” mapping files, since I didn’t know until I ran the program when I had misspelled something.  Since the innovation program still in incubation when I finished, I set my proof-of-concept aside.

Fast forward a few months, and I had noticed that the Fluent NHibernate project had come a long way.  They’ve now got  a significant amount of documentation on their wiki site (http://fluentnhibernate.org/), pre-built binary packages, and a pretty active mailing list (http://groups.google.com/group/fluent-nhibernate).  After perusing the site a bit, and determining that, based on the amount of activity I saw, Fluent NHibernate probably did have some legs and wouldn’t just be a flash in the pan, I decided to convert proof-of-concept over to using Fluent NHibernate.

I was not disappointed.  One of the key benefits of using FNH is that you get compile-time checking of your object property names, since you use lambda expressions to specify your mappings.  You also don’t have to use the verbose type name syntax (e.g. “My.Really.Long.Chain.Of.Namespaces, ClassName”) when creating relationships between entities.  But the thing I liked the most was the ability to define conventions for just about everything.

The team I work on has an… ahem… interesting pattern for column naming:  basically, Hungarian notation for columns.  If a column is an integer column in the database, it will have an “int” prefix on the column name.  If it’s a char or varchar column, it will have a “str” prefix, and so on.  While I may not agree with this “coding standard”, the team has at least been consistent about it, so I was able to take advantage of conventions.  

In FNH, you define a convention by creating a class that implements one of the convention interfaces provided by FNH, such as IPropertyConvention (you can see the entire list of available interfaces here).  That interface requires you to implement two methods, Accept and Apply.  

The Accept method lets you define what kinds of properties or classes will be affected by the convention.  You get full access to all of the information about the property, such as the name, the data type, and so on, to let you determine if the convention ought to apply to the property.  For example, the Accept method for the string column convention I mentioned earlier looks like this:

public bool Accept(IProperty target)

    return target.PropertyType == typeof (string);
}

The Apply method lets you perform mapping actions on the property or class just as you would in a ClassMap<T> class, which is where mappings are defined in FNH (each one of those classes would correspond to a “hbm.xml” file used by NHibernate when not using FNH).  This is easier shown than explained, so here’s the Apply method for that string column convention:

public void Apply(IProperty target)
{
    target.ColumnNames.Add("str" + target.Property.Name);
}

So, with that convention in place, all I have to do to define a mapping between an entity property named Address and a column named strAddress is:

Map(x => x.Address);

You can, of course, override the conventions you define at any point that you system deviates, so you’re never painting youself into a corner by defining conventions. You’re just taking care of the majority case, and eliminating a lot of code (and magic strings) in the process.  

Since I had conventions and Intellisense working for me, I was able to convert all the hbm.xml mappings I had defined the first time to FNH mappings in a single evening.  If you’re using NHibernate in your application, you should take a serious look at Fluent NHibernate.  Not just for the reasons I’ve covered here, but also for the help it provides with refactoring (property names in mappings are affected by refactoring tools) and the ability to test your mappings.  Kudos to James Gregory,  Paul Batum, Andrew Stewart, Chad Myers, Jeremy Miller, et al. for providing a way for the rest of us to improve our NHibernate experience.

2 thoughts on “Fluent NHibernate Rocks

  1. Chad Myers

    Brian,

    Glad you liked it! You should know, as well as your readers, that James Gregory deserves a lion’s share of the credit. While we all have contributed (some more significantly than others [Paul and Andrew, plus others]), James, I feel, has been the primary contributor and deserves the most praise and kudos. I hope Paul and Andrew would agree.

    Also, Jeremy Miller should be given some credit since it was originally his brainchild and he put together most of the initial code to bootstrap the project.

    Reply
    1. admin Post author

      @Chad,

      Thanks for the clarification! I certainly want to give credit where it’s due. I actually read the “please address beers to” section of the FNH main page and missed the copyright section at the bottom! I’ve corrected the post to add James and Jeremy to the list. In any case, thanks for your contribution to the project, as well!

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *