Fluent NHibernate is a very popular framework, but for me, it has a few issues. I find the API somewhat hard to discover (it is an abstraction over the XML configuration which I know well), and sometimes features I really want aren’t implemented, or take some time to arrive. This of course isn’t the FNH teams fault, but FNH has a huge scope and the extension points aren’t always there.
I ended up writing my own system for typed mappings that I feel is simpler, and allows you to build a mapping framework that does exactly the job you need it to. This series of posts will introduce the approach.
Given the formula domain assemblies + automapping framework = nhibernate mapping.xml it is obvious we will need to somehow manipulate and produce an nhibernate mapping xml file in a structured way, using c# code. The way I do this is to use the LINQ To Xsd project to generate a statically typed representation of an NHibernate mapping file. Here is a simple mapping file, with the classic xml mapping on the left (thanks fincher.org), and Linq To Xsd mapping on the right:
You can see how similar the xml and the code are. This allows you to use easily migrate from xml mapping to code mappings. We can get rid of magic strings and make the mapping refactor proof very easily, e.g. by replacing "NHibernatePets.Pet, NHibernatePets" with typeof(Pet).AssemblyQualifiedName, and using static reflection to get the property names.
To try this out, download nhibernate-configuration.cs and nhibernate-mapping.cs (the LINQ to XSD generated files) and include them in your project, then bootstrap your NHibernate configuration using this snippet:
public static Configuration GetConfiguration(string connectionString)
{
var cfg = new Configuration();
var mappingXDoc = new hibernatemapping()
{
//add your mappings here
};
cfg.SetProperty(NHibernate.Cfg.Environment.Dialect, "NHibernate.Dialect.MsSql2008Dialect");
cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionDriver, "NHibernate.Driver.SqlClientDriver");
cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionString, connectionString);
cfg.SetProperty(NHibernate.Cfg.Environment.ConnectionProvider, "NHibernate.Connection.DriverConnectionProvider");
cfg.SetProperty(NHibernate.Cfg.Environment.ProxyFactoryFactoryClass, typeof(ProxyFactoryFactory).AssemblyQualifiedName);
cfg.AddXml(mappingXDoc.ToString());
return cfg;
}
Now you should be able to get started with writing typed mappings. Next time we’ll get started on conventions.

5 comments: