Fluent
This is the newest way of doing OR/M in NHibernate. It works by providing a constructor that will establish the mappings using a Map() method, and by inheriting from a NHibernate provided class, like this:
public CustomerMap : ClassMap<Customer>
{
public CustomerMap()
{
Id(x => x.ID);
Map(x => x.FirstName);
Map(x => x.LastName);
HasMany<Address>(x => x.Addresses)
.AsBag();
}
}
You can find more information about this type of mapping in James Gregory’s blog.
Fluent mapping is cool, and it’s the newest way of mapping. This way of mapping is not officially supported, and it doesn’t cover every possible mapping, but it’s type safe (as it’s fluent), it’s really simple and it doesn’t use Xml. Also, since the mapping class is outside of the “Model” class, the model integrity is preserved.
Attributes
Attributes are also a very effective way of mapping without using Xml. When you use attributes, NHibernate creates the Xml for you on runtime. That is, you may not be using the xml config files, but the files are being generated and used anyway. Attributes are used like this:
[NHibernate.Mapping.Attributes.Class]
public class Customer
{
[NHibernate.Mapping.Attributes.Id(0, TypeType=typeof(int))]
public int ID;
[NHibernate.Mapping.Attributes.Property]
public string FirstName;
[NHibernate.Mapping.Attributes.Property]
public string LastName;
}
The cool thing about attributes is that you don’t violate the DRY principle. You do violate it (a lot) when using xml files. The bad thing about attributes is that they are all over your model. That pushes NHibernate all over the place instead of leaving it in your persistance layer (where it should be). Also, the attributes require a certain order, which is counterintuitive to the way attributes are generally used.
Xml
Xml is the standard format for configuration. It looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="MyNamespace" assembly="MyAssembly">
<class name="Customer" table="Customers">
<id name="ID">
<generator class="identity" />
</id>
<property name="FirstName" />
<property name="LastName" />
<bag name="Addresses" table="Addresses">
<key column="CustomerID"/>
<one-to-many class="MyNamespace.Address, MyNamespace"/>
</bag>
</class>
</hibernate-mapping>
This format is slightly more complex than the others, and it’s inherently not safe as it’s Xml and not code. It also forces you to repeat information already stated (class names, property names, etc). On the other hand, it’s completely transparent to your code, allowing you to take NHibernate out of the picture at any time, or adding it with no changes to your model.
How this affects code generation
If you’re generating your DAL using T4, your perspective on some of these issues may change a little. First, even though DRY is an important principle, it isn’t as important in code generation. You’re not repeating yourself, the generated code is. There’s a difference there: only one set to maintain (not two), and if the code is being regenerated in each build, then there’s nothing to maintain. That eliminates the main advantage of using attributes.
Also, type safety isn’t that important because in generated code you’re not actually writing the code. Compile time safety is cool, but if your code is being properly generated you don’t have a big error-prone surface in the configuration. That eliminates the main advantage of using Fluent configuration.
In code generated code, I always try to make the code as close as possible as code I would have written by hand. That is, no weird names, standard data types, regular patterns. Both Fluent (to a lesser extent) and Attributes provide a very strong binding to NHibernate. Also, Fluent is not (yet) fully functional and fully supported. Xml is still ugly, but it’s being generated automatically and it shouldn’t be modified by the developer.
That’s why in the context of code generation I prefer to use Xml configuration instead of Attributes or Fluent.
--
Written by Joaquin, joj AT clariusconsulting DOT net. Disclaimer: opinions expressed in this post are my own and not necessarily reflect those of Clarius Consulting.

Nice post, however I do have to question why you think Fluent is unsupported? There's an active mailing list with nearly 300 users, of which I or other Fluent committers reply to questions all hours of the day. I'd say we're as supported if not more than Attributes.
ReplyDeleteWhen I wrote "not officially supported", I meant "not part of the main NHibernate branch". I didn't mean that support was lacking, sorry for the misunderstanding. I'm going to update the post to reflect this.
ReplyDelete"That’s why in the context of code generation I prefer to use Xml configuration instead of Attributes or Fluent."
ReplyDeleteYes! That's right!
Fluent new form to mapping ... but ... i need two files ! mapping and class, pros ?
ReplyDelete