Managing NHibernate Maps
When using NHibernate sometimes your mapping files get a little out of hand, especially if you’re putting all your mappings into a single file.
We initially started out with a one-to-one relationship between a mapping file and what DDD calls a Module. In DDD a Module is a grouping of related classes around which you want to exert - at least - conceptual control over the dependencies inside and out. In my mind it’s the next order of magnitude above the Aggregate Root pattern… more cell wall than nucleus wall.
Anyway, this model of having a mapping file per 3-8 related classes became kind of cumbersome for me. When you’re opening an XML file that can be a few hundred lines long, and it’s easy to lose your place when tracking a relationship mapping or just going through a class that has a dozen or so properties in it. Of course, one of the best practices mentioned in the NHibernate documentation is to “place each class mapping in its own file.” I switched to that model and have noticed a nice improvement in map discoverability and workflow; I can now CTRL+TAB between a few screens that have related mappings. I guess it pays to read, eh?
This weekend I was adding a couple of features to our Domain Model for contact management. It became sensible at a certain point in the design to introduce an inheritance relationship between a few of the classes. I decided to use an abstract base class and the “table per subclass” strategy offered by NHibernate. This is done by defining the base class in the usual class mapping then adding joined-subclass mappings. For a while I couldn’t figure out how to break out the mappings for the subclasses until I noticed:
It is possible to define subclass and joined-subclass mappings in separate mapping documents, directly beneath hibernate-mapping. This allows you to extend a class hierarchy just by adding a new mapping file. You must specify an extends attribute in the subclass mapping, naming a previously mapped superclass. Use of this feature makes the ordering of the mapping documents important!
The provided sample mapping:
<hibernate-mapping> <subclass name=”Eg.Subclass.DomesticCat, Eg” extends=”Eg.Cat, Eg” discriminator-value=”D”> <property name=”name” type=”string”/> </subclass> </hibernate-mapping>
I was unsure what the part “makes the ordering of the mapping documents important!” of the documentation meant, so I tried it in one of our Domain Models. Using embedded mappings (”Embed As Resource”) it worked without a hitch. My suspicion is that the load order matters when you are loading your mapping files programmatically and external to your assembly via NHibernate’s Configuration.AddFile().
DotNetKicks.com wrote:
Managing NHibernate Maps…
You’ve been kicked (a good thing) - Trackback from DotNetKicks.com…
Posted on 15-Jan-07 at 1:43 pm | Permalink
Evan wrote:
This is some really good practical advice! Thanks for sharing. :-)
Posted on 15-Jan-07 at 9:42 pm | Permalink
Ben Scheirman wrote:
I have followed the mapping-per-concrete-class strategy and I like it a lot. I get used to seeing 2 of every class (Item.cs, Item.hbm.xml for example).
It’s a matter of personal preference, but I find that method the easiest to manage.
Posted on 27-Jan-07 at 2:22 pm | Permalink
Eduard Liebenberger wrote:
It means that you have to set the “skipOrder” parameter to “false” when you use calls like “Configuration.AddAssembly” etc. NHibernate documentation recommends to set this parameter to “true” to increase performance (and I believe this is the default setting).
And in case you manually add the mapping files you already mentioned that it will be the developer’s responsibility to keep a proper order.
However if the mapping files (and the inheritance hierarchies) are split across multiple assemblies the configuration is still not totally robust (Release 1.2 GA).
Posted on 09-May-07 at 7:52 pm | Permalink