Fluent NHibernate
Auto Mapping (changes)

Showing changes from revision #1 to #2: Added | Removed

Fluent NHibernate has a concept called Auto Mapping, which is a mechanism for automatically mapping all your entities based on a set of conventions.

Auto mapping utilises the principal of convention over configuration. Using this principal, the auto mapper inspects your entities and makes assumptions of what particular properties should be. Perhaps you have a property with the name of Id and type of int, the auto mapping might (and will by default) decide that this is an auto-incrementing primary key.

By using the auto mappings, you can map your entire domain with very little code, and certainly no XML. There are still scenarios where it may not be suitable to use the auto mapping, at which point it would be more appropriate to use the standard mapping; however, for most greenfield applications (and quite a few brownfield ones too) auto mapping will be more than capable.

Getting started with a simple example

Although it isn't the purpose of this post give an in-depth walkthrough of Auto Mapping, it's not out of scope for a simple example! So I'll go through how to map a simple domain using the Fluent NHibernate AutoMapper.

Imagine what the entities might be like for a simple shop; in-fact, let me show you.


public class Product
{
  public virtual int Id { get; private set; }
  public virtual string Name { get; set; }
  public virtual decimal Price { get; set; }
}

public class Shelf
{
  public virtual int Id { get; private set; }
  public virtual IList<Product> Products { get; private set; }

  public Shelf()
  {
    Products = new List<Product>();
  }
}

You can't get much simpler than that. We've got a product, with an auto-incrementing primary key called Id, a Name and a Price. The store has some shelves it fills with products, so there's a Shelf entity, which has an Id again, and a list of the Products on it; the Product collection is a one-to-many or Has Many relationship to the Product.

I'm going to make the assumption here that you have an existing NHibernate infrastructure, if you don't then it's best you consult a general NHibernate walkthrough before continuing.

We're going to be using the AutoPersistenceModel to do our mapping, which you can use in combination with the Fluent Configuration API. To begin with we should take a look at the static MapEntitiesFromAssemblyOf<T> method; this method takes a generic type parameter from which we determine which assembly to look in for mappable entities.


AutoPersistenceModel.MapEntitiesFromAssemblyOf<Product>();

That's it, you've mapped your domain... Ok, there might be a little bit more to do than that. Let me explain.

The MapEntitiesFromAssemblyOf<T> method creates an instance of an AutoPersistenceModel that's tied to the assembly that Product is declared. No mappings are actually generated until you come to your entities into NHibernate.

We're going to utilise the Fluent Configuration API to create our SessionFactory.


var sessionFactory = Fluently.Configure()
  .Database(MsSqlConfiguration.MsSql2005
    .ConnectionString(c => c
      .Is(ApplicationConnectionString)))
  .Mappings(m =>
    .m.AutoMappings.Add(AutoPersistenceModel.MapEntitiesFromAssemblyOf<Product>())
  )
  .BuildSessionFactory();

You can see that our AutoPersistenceModel is sat in the middle of the configuration, inside the Mappings call; this is our way of telling Fluent NHibernate that we're using the Auto Mapper.

We're now capable of getting NHibernate to accept our auto mapped entities, there's just one more thing we need to deal with. The auto mapper doesn't know which classes are your entities, and which ones are your services (and everything else). The setup we're using above simply maps every class in your assembly as an entity, which isn't going to be very useful; so I'll introduce one final method: Where(Func<Type, bool>).

The Where method takes a lambda expression which is used to limit types based on your own criteria. The most common usage is limiting based on a namespace, but you could also look at the type name, or anything else exposed on the Type object.


var autoMappings = AutoPersistenceModel
  .MapEntitiesFromAssemblyOf<Product>()
  .Where(t => t.Namespace == "Storefront.Entities");

Bringing all that together leaves us with this NHibernate setup:


var sessionFactory = Fluently.Configure()
  .Database(MsSqlConfiguration.MsSql2005
    .ConnectionString(c => c
      .Is(ApplicationConnectionString)))
  .Mappings(m =>
    .m.AutoMappings.Add(
      AutoPersistenceModel.MapEntitiesFromAssemblyOf<Product>()
        .Where(t => t.Namespace == "Storefront.Entities")
    ))
  .BuildSessionFactory();

That's all there is to automatically mapping your domain entities. It's all a lot easier than writing out mappings, isn't it? There's much more to the auto mapping that I haven't covered here, and I hope to write about those soon. Until then, enjoy!