Create NHibernate classes using T4

Overview

Over the last little while there have been a raft of posts about using T4 templates, I think most of this seemed to be sparked from the drive to extend and gain more control over the Linq-to-Sql classes. So while there are a few good T4 templates to convert DBML files into classes there have been a number of drawbacks, some of these are pointed out here. The fact that L2S doesn’t support many-to-many relationships and the designer doesn’t let you specify the column lengths make using it for NHibernate (NH) related purposes fall a little short.

NHibernate XML Intellisense

On the next point, I know there has been a fair amount of hype around the Fluent NHibernate Mapping scene as well. I have never really found a few XML mapping files that hard to deal with. Here’s why:

image

Yep, once you’ve added the xsd definitions into Visual Studio’s schemas folder there’s intellisense and validation over any NH config.

T4 for Hbm.xml

If you’re creating a new project there is always the hassle of ensuring that your NH mappings have the same properties as your classes and all the methods and properties are virtual etc. So instead of converting a DBML file to NH mappings and classes, as mentioned before it is not really intended for this purpose. Here’s a small T4 template that you can use to convert .hbm.xml files into partial classes. So now, all you need to do is maintain an xml mapping file and let your class properties be automatically synchronised. My sample solution looks like this:

image

Inside the “BusinessObjectsGenerator.tt” is a simple generator that includes the desired business object structure and then specifies which xml files in the solution to generate partial classes for. The classes are partial so you can extend them with custom changes if needed in another file.

<#@ template language="C#v3.5" debug="True" hostspecific="True"  #>

<#@ include file="..\..\T4Templates\BusinessObjectsStructureTemplate.tt" #>
<#@ output extension="log" #>
<#

BusinessObjectStructureTemplate template = new BusinessObjectStructureTemplate();
var pathBase = new System.IO.FileInfo(Host.TemplateFile).DirectoryName;

BusinessObjectStructureTemplate.RenderClassFromHbm(pathBase, @"Mapping\Product.hbm.xml", template);
BusinessObjectStructureTemplate.RenderClassFromHbm(pathBase, @"Mapping\Order.hbm.xml", template);
BusinessObjectStructureTemplate.RenderClassFromHbm(pathBase, @"Mapping\Customer.hbm.xml", template);

#>

If you’ve previously downloaded and looked into Damien’s L2S templates they look fairly complex. The easiest way I’ve found to produce T4 is with the T4 toolbox, and also using the T4 Editor by Tangible Engineering. However, currently if you’ve download the T4Toolbox, I had to download and compile rev#34560 which corrects an error when having T4 templates in a project that is nested in a solution folder.

On the inside

Most of the work is done inside the “BusinessObjectsStructureTemplate.tt” file. What I’ve done to try and keep things simple is use NH’s own ‘MappingDocumentParser’ class to parse the Xml file, then simply iterate through the config to populate some custom data structures that are applied to the template. The reason for this is the custom data classes inside the T4 templates can be extended and changed later if more flexibility is needed, also meaning a new adapter could be written instead of the NH version.

Sourcecode

Visit the T4 repository

Choose one of these:

  • System.BusinessObjects version: BusinessObjectsStructureTemplate.tt
  • Generic POCO version: BusinessObjectsStructurePOCOTemplate.tt

And then include that file into the generator:

  • BusinessObjectsGenerator.tt

Links

Create NHibernate classes using T4

Print | posted on Sunday, July 19, 2009 11:00 AM

&uot&uot

Comments on this post

# re: Create NHibernate classes using T4

Requesting Gravatar...
what a great info, thanks for that.
Left by Sulumits Retsambew on Aug 03, 2009 4:50 AM

# re: Create NHibernate classes using T4

Requesting Gravatar...
When i use your t4 code i got always following error:

Error 3 Compiling transformation: Type of conditional expression cannot be determined because there is no implicit conversion between 'NHibernate.Cfg.MappingSchema.HbmType' and 'string' c:\Daten\Work\VisualStudio2008\NHibernateGenerator\DataLayer\Mapping\BusinessObjectsStructureTemplate.tt 136 82 DataLayer


Whats Wrong?
Left by Viktor Frick on Sep 16, 2009 9:53 PM

# re: Create NHibernate classes using T4

Requesting Gravatar...
Hi Viktor,

These templates can convert common properties/options into C# classes. Most other situations are easy to change and extend. Without seeing the mapping file I can't tell you the exact problem, but I can tell you there is a method inside BusinessObjectStructureTemplate.tt called "RenderClassFromHbm" which is having problems trying to convert the ID/Primary Key field. See code.google.com/.../Product.hbm.xml for my example. Please get back to me and we can extend the template to handle your config.

Brendan
Left by Brendan on Sep 16, 2009 10:36 PM

# re: Create NHibernate classes using T4

Requesting Gravatar...
Hi Brendan,
thank you for you reply.
i have downloaded your hole solutions and when i save the product.hbm.xml i get the following error:

Error 1 Compiling transformation: Type of conditional expression cannot be determined because there is no implicit conversion between 'NHibernate.Cfg.MappingSchema.HbmType' and 'string' c:\Daten\Work\VisualStudio2008\T4BusinessObjects\T4Templates\BusinessObjectsStructureTemplate.tt 136 82

Error 2 Compiling transformation: 'NHibernate.Cfg.MappingSchema.HbmSet' does not contain a definition for 'Item1' and no extension method 'Item1' accepting a first argument of type 'NHibernate.Cfg.MappingSchema.HbmSet' could be found (are you missing a using directive or an assembly reference?) c:\Daten\Work\VisualStudio2008\T4BusinessObjects\T4Templates\BusinessObjectsStructureTemplate.tt 168 75

Could you help me ?
Thanks
Viktor
Left by Viktor Frick on Sep 18, 2009 10:33 PM

Your comment:

 (will show your gravatar)
 
Please add 4 and 8 and type the answer here: