Fluent NHibernate Auto Persistence Model

I wrote the other day about how conventions in Fluent NHibernate can make your life easier by decreasing the amount of code you have to write to map your objects to their relational representations.  Well, if you’re willing to go along with even more convention, you can even do away with some of your mapping files entirely.

When setting up your NHibernate configuration via FNH, normally you specify where to find your mappings by using something similar to the following:

.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Entity>())

Notice the “FluentMappings” property being used here.  This will look for any mappings you have explicitly specified in classes that derive from ClassMap, a base class provided by FNH.  However, if we change that to use the “AutoMappings” property instead, like so:

.Mappings(m => m.AutoMappings.Add(AutoPersistenceModel.MapEntitiesFromAssemblyOf<Entity>()))

FNH will determine the mappings all by itself based on conventions, and you don’t have to write a single ClassMap class.

Used in conjunction with NHibernate’s SchemaUpdate feature, this becomes really powerful.  You can simply add a property to an entity class contained in an assembly for which you are using auto mapping.  When you run SchemaUpdate, either at the start of your application, or maybe in a separate console app, your database schema will be updated to include a new column to store that property value.  To illustrate, I’ll show you a simple example.  

I’ve got a small entity named “Course” that represents a college course.

    public class Course
    {
        public virtual int Id { get; private set; }
        public virtual string Name { get; set; }
        public virtual string CatalogNumber { get; set; }
    }

And the database table it maps to looks like this:

sql1

Say that I wanted to add a property to my Course entity to tell how many credits the course was worth.  I just add the property to the class:

    public class Course
    {
        public virtual int Id { get; private set; }
        public virtual string Name { get; set; }
        public virtual string CatalogNumber { get; set; }
        public virtual int NumberOfCredits { get; set; }
    }

And run SchemaUpdate through a simple console app that looks like this:

    class Program
    {
        static void Main(string[] args)
        {
            Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2005
                .ConnectionString(c =>
                    c.Is(ConfigurationManager.ConnectionStrings["SQLServerConnString"].ConnectionString)))
            .Mappings(m =>
                  m.AutoMappings.Add(AutoPersistenceModel.MapEntitiesFromAssemblyOf()))
            .ExposeConfiguration(BuildSchema)
            .BuildConfiguration();
        }

        private static void BuildSchema(Configuration config)
        {
            new SchemaUpdate(config).Execute(true, true);
        }
    }

I’ll see the script being used to update the schema in the console window:
console

And my database table will be updated with a new column for the new property:

sql2

Having not used this feature of Fluent NHibernate in anything close to a production capacity, I can’t speak to how well it scales.  However, I think this has a lot of potential for rapid prototyping, especially when you pair it with ASP.NET MVC and the templated controllers and views that you can generate.  A little alteration of the T4 templates used for the controllers could do some default persistence via NHibernate, and then we’d be quite a bit closer to the ease of protoyping provided by Rails.

Again, hats off to the Fluent NHibernate team!

4 thoughts on “Fluent NHibernate Auto Persistence Model

  1. Pingback: Fluent NHibernate « Net

  2. Pingback: Follow « Net

  3. Mike

    Thanks for your post, but for some reason with the RTM version of fluent nhibernate, I get a cannot resolve symbol MapEntitiesFromAssemblyOf. What version of fluent are you using? and what are your using clauses?

    Thanks!

    Reply

Leave a Reply

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