NHibernate 32 and Mapping By Code

In version 3.2 of NHibernate a new mapping capabilities was introduced to easy mapping of entities in your project. To understand how it works and how easy it is here it is all initialization code you need if you want to accept default mapping rules for all of your classes.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
cfg = new Configuration();
var mapper = new ConventionModelMapper();
mapper.IsEntity((t, declared) => t.Namespace.StartsWith("Myproject.Entities"));
mapper.AfterMapClass += (inspector, type, classCustomizer) =>
{
    classCustomizer.Lazy(false);
};
var mapping = mapper.CompileMappingFor(
    Assembly.GetExecutingAssembly().GetExportedTypes()
   .Where(t => t.Namespace.StartsWith("Myproject.Entities")));

cfg.AddDeserializedMapping(mapping, "AutoModel");
cfg.BuildSessionFactory();

Basically I’m creating a * ConvetionModelMapper *that is capable of mapping entities by convention, then the IsEntity method is used to specify a condition to make the mapper aware of the classes that needs to be mapped ; in this example I simply states that everything that is in namespace Myproject.Entities should be mapped. Since I want lazy load to be disabled I register an handler on AfterMapClass, an event that is launched whenever an entity is mapped, and I simply disable lazy load stating Lazy(false). In this super simple example all the entities are in the same assembly of this function, so I can pass the executing assembly to the CompileMappingFor() method of conventional mapper, specifying again the list of class I want to be mapped. Finally I can simply use AddDeserializedMapping method of Configuration object to add the mapping generated by CompileMappingFor and the game is done. Now you can create this simple class in Myproject.Entities

1
2
3
4
5
6
7
8
9
public class Customer
{

    public Int32 Id { get; set; }

    public String Name { get; set; }

    public String Surname { get; set; }
}

And let NHibernate generate the database, you got this table automatically generated in the database.

image

Figure 1: Table generates by automapping in the database.

The main problem of this approach is that this table has not Identity on Id column and all the nvarchar columns have 255 length , because this is the default of NHibnernate. Now you can solve this problem with two different approaches, the first is keeping track of your database with a different tool, like Database Projects in Visual Studio, because probably you have other part of the database that is not related to nhibernate (like stored procedure) that you need to manage. To simply this process I usually let nhibernate generate a test database when I add new entities, then I simply synchronize my database project to grab all the differencies, and then I refine them adding identities, length etc.

If you want NHibernate to manage all stuff of database creation and Updating, you need to give more detail to the Conventional mapper. Here is an example.

1
2
3
mapper.Class<Customer>(map => map.Id(c => c.Id, mapInfo => mapInfo.Generator(Generators.Native)));
mapper.Class<Customer>(map => map.Property(c => c.Surname, mapInfo => mapInfo.Length(40)));
mapper.Class<Customer>(map => map.Property(c => c.Name, mapInfo => mapInfo.Length(40)));

This approach can be useful if you have few entities, but when your domain is quite complex, it is slightly better to use a Database Project that gave you more control over the structure of the database with a tool dedicated to this purpose.

Gian Maria.