Fluent NHibernate’s AutoPersistenceModel


Much of this information may be out of date, please check http://fluentnhibernate.org/ for current information.

Almost too Easy

I was really excited when I learned about this piece of the Fluent NHibernate project. I’m working on a small project with some simple mappings. I started looking to Castle’s Active Record for some quick persistence assistance, but I wasn’t thrilled with the Attributes, or the ActiveRecordMediator approach. I decided to go back to “plain old” NHibernate, but use this Fluent NHibernate project I’ve been hearing about lately.

Ayende posted last month about the auto-mapping the AutoPersistenceModel provides and how’s loving it. I too am loving it and it only gets better each day.

Let’s Start With Conventions

Below is the code I’m using in my project to generate my persistence schema. First I’ll go over the Conventions class:

model = new AutoPersistenceModel
{
Conventions =
{
DefaultLazyLoad = true,
GetPrimaryKeyName = (prop => prop.ReflectedType.Name + prop.Name),
GetForeignKeyNameOfParent = (type => type.Name + "Id"),
GetForeignKeyName = (prop => prop.ReflectedType.Name + "Id"),
GetTableName = (type => Inflector.Pluralize(type.Name)),
GetManyToManyTableName =
((child, parent) =>
parent.Name + Inflector.Pluralize(child.Name))
}
};

This is basically straight out of Ayende’s example, I modified the conventions a bit so it matches the conventions I was aiming for in the project. Most of these are very straightforward as to what they’re doing for you, but I’ll give a quick explanation to what these Conventions are doing for my mappings:

Among others, I have a Stat class and I have a Tag class. These are my primary objects and persisted data, so I’ll let you know what the Conventions will create for them:

  • GetPrimaryKeyName
    • Assigned the Func that will return the values “StatId” and “TagId” (Note: I’m using type.ReflectedType since this Func uses ‘type’ as a PropertyInfo object, otherwise, I’d get “IdId”)
  • GetForeignKeyNameOfParent 
  • GetForeignKeyNameOfParent 
    • Will return “StatId” and “TagId”
  • GetForeignKeyName 
    • Will return “StatId” and “TagId” as well. My Stat class has a Submitter Property, which makes sense in my code, but at the database level, I want it to be ‘UserId’.
  • GetTableName
    • Will return Stats and Tags (thanks to the Inflector class provided by Castle’s ActiveRecord) If you needed a convention to map here, such as S_ prefixed to table names for existing systems. Here’s where you’d do that.
  • GetManToManyTableName
    • Asks you to provide the child and the parent Types to create a convention. My example will generate StatTags. You would use this to specify others such as “TagsToStats” or “Tags_x_Stats”

Adding Your Entities

Ok, now that we have the Conventions (rules) set up. Time to tell this thing what we want to be persisting. I took yet another tidbit from Ayende and used his entity.Namespace.EndsWith(“Models”) idea. My code is simple here, I don’t have a lot of stuff going on that needs special attention. I simply added my assembly like so:

model
.AddEntityAssembly(Assembly.GetAssembly(typeof (User)))
.Where(entity =>
entity.Namespace.EndsWith("Model") &&
entity.GetProperty("Id") != null &&
entity.IsAbstract == false
)
.Configure(configuration);

That’s it, seriously. I still have to add my NHibernate configuration, so here is that:

configuration = MsSqlConfiguration.MsSql2000
.ConnectionString.Is(connectionString)
.UseReflectionOptimizer()
.Cache.UseQueryCache()
.Cache.ProviderClass()
.ConfigureProperties(new Configuration());

All I do from this point on is call NHibernate.Tool.hbm2ddl.SchemaExport(configuration) when I need a SQL file to update my database schema.

Why is this better than Xml Configuration?

Before acquiring amazing tools like JetBrains’s Resharper, I would rename a property and then try to build to see where I couldn’t compile, and appropriately rename the usages of that property elsewhere. Now I can rename it and it will cascade to all my other usages, renaming them to the same thing. Whether you’re using a tool like this or not, you may still deal with “Magic Strings“. Using Fluent NHibernate eliminates these occurences by getting rid of the Xml files that store these nasty characters.

Another reason… Xml files as an embedded resource in order to compile the mappings? You don’t have to deal with that anymore.

What’s to Come?

This project really excites me. It’s easy to use and it’s only getting better. Eventually it might be as simple as not having to tell the AutoPersistenceModel that: entities have a property Id as a Guid, and all my tables are going to be prefixed. I’m hoping it gets to a point where you just give it an assembly and you’re good to go (so long as you don’t have any crazy rules!)

Stay tuned to this project! There are a lot of talented people working on it and as I said earlier, you can expect new features all the time.

Here’s the link to the project: http://code.google.com/p/fluent-nhibernate/

Who is this Chris Missal Guy?