When ActiveRecord, when (Fluent) NHibernate?

I’ve recently been working on a fairly straight forward WCF Web-Service using Castle ActiveRecord, which uses NHibernate under the hood.

So far, I’ve been really impressed with ActiveRecord as a well throught through abstraction of NHibernate’s key features, which does a great job of keeping you focussed on the important stuff, without getting bogged down in the config.

I don’t want to go into depth on this here, but just to give you a quick idea if you haven’t seen this before, you simply add the attributes to your entities to describe how you want them persisted:

1
2
3
4
5
6
7
8
9
10
11
12
13
[ActiveRecord]
public class UpdatePersonMessage : BaseObject
{
    [PrimaryKey(Generator=PrimaryKeyType.GuidComb)]
    public virtual Guid Id { get; set; }
 
    [Property(Length = 50)]
    public virtual string FirstName { get; set; }
 
    [Property(Length = 50)]
    public virtual string LastName { get; set; }
    ...
}

You can then get ActiveRecord to dynamically create your database on initialisation, with a single line of code:

1
ActiveRecordStarter.Initialize(typeof(UpdatePersonMessage));

OR, if you want to use a custom config location… (I’ve had to format a little strangley to prevent this scrolling)

1
2
3
4
IConfigurationSource config = 
      new XmlConfigurationSource("{pathto}/ActiveRecord.config");
ActiveRecordStarter.Initialize(config, 
      typeof(UpdatePersonMessage));

So, on the last coulpe of projects where I’ve used ActiveRecord, I’ve been thinking – when would I bother using NHibernate, having to create all the relevant XML mapping files either by hand, or via a tool such as MyGeneration, or by using the declarative API for configuration provided by Fluent NHibernate?

As far as my experience tells me, there are only just a few key questions you can ask that can help you decide whether or not:

Please note: this already assumes that a full ORM is the appropriate solution for your domain – see YAGNI principle if you are not sure

  1. How complex is your data model? (e.g. beyond 3NF/BCNF, or complex legacy)
  2. Is this is a sensitive legacy datasource, tightly coupled to other legacy applications?
  3. How many people will be making changes to the data model, and how often?

The more complex the requirement, the more you move away from a situation that would get the best out of ActiveRecord. The approach is deliberatly simple, and while the pattern can cope with most day-to-day projects, as soon as your data requirements become more bespoke, it could be worth reconsidering an approach using NHibernate nativley.

Mapping files, attributes or declarative C#

Almost treated as a secondary design decision is how to manage the mapping of your data model.

If you use XML configuration files with a large team who all have access and make frequent changes, it can be a nightmare to manage. and you’ll quickly find yourself in the situation where you’ll be wondering why a particular persistence routine isn’t producing the expected behaviour anymore, and it’s simply down to a change you were not aware of.

Obviously TDD can really help with this, as can limiting access to just a couple of key developers who take ownership of the data model (and lock the mappings section down in source control!). On most projects, a data architect or lead dev would already have been allocated this role anyway.

Managing the mapping using C# code (e.g. using Fluent NHibernate) is often the best alternative if you’re not using ActiveRecord (or another configuration abstraction layer) for a number of reasons:

  1. No Type-Safety = runtime explosions
  2. No Intellisense
  3. Your code will always compile regardless of how present, or correct your mapping files are

Here’s an example of Fluent NHibernate in action:

1
2
3
4
5
6
7
8
9
10
public class UpdateExhibitorMessage : BaseObject
{  
    public UpdatePersonMessage()  
    {  
        Id(x => x.Id);  
        Map(x => x.FirstName);  
        Map(x => x.LastName);
        ...
    }  
}

then, using the Auto Persistence Model – you can create the schema in the much same way as ActiveRecord:

AutoPersistenceModel.MapEntitiesFromAssemblyOf<UpdatePersonMessage>().Configure(config);

Summary

I have to admit… this has been a rushed post and none of these ideas are particularly new, but my aim is really to make it clear that there are several different decisions involved in getting the right NHibernate implementation to suite your problem domain and your team that begin AFTER you’ve made the decision to use NHibernate, and each of these decisions need to be thought through carefuly, because – as with software development in general – there is never a one-size-fits-all approach.


Quick Post-Edit Note: Be weary of any developer suggesting you use a particular pattern or framework with being able to solidly defend the specific benefits to your current solution. I know it sounds obvious, but it’s crazy how often you come across “CV++” or developers sticking to ‘what they used on their last project’ without choosing the approach that is the right fit for your current domain.