Using T4 templates with the NHibernate Designer

The NHibernate Designer is a great way to design data models for use with the NHibernate object-relational mapper. But once you’ve captured your data model, you may be interested in generating other code from it — anything from data transfer objects (DTOs) right through to scaffolding for a simple admin site. In some cases you can do this by editing the designer’s NVelocity templates, but sometimes you want to generate content that doesn’t fit in a C# or VB file, or maybe you just don’t like NVelocity. (I can sympathise with that.) Fortunately, you can use Visual Studio’s standard T4 templating system to do your own code generation off a NHibernate model. Let’s dive in!

Creating the template

To create a T4 template, add a new item to your project and choose Text Template. This gives you an empty starter T4 file.

Next, you need to hook the template up to the NHibernate Designer DLLs. You do this in two parts. First, you add the following incantation to the template directive:

<#@ template inherits="Microsoft.VisualStudio.TextTemplating.VSHost.ModelingTextTransformation" ... #>

Don’t worry about what this means — it’s just a bit of plumbing to bring in the same Visual Studio subsystem that the NHibernate Designer sits over. Next, you add a couple of assembly references:

<#@ assembly name="Mindscape.NHibernateModelDesigner.DataModel.dll" #>
<#@ assembly name="Mindscape.NHibernateModelDesigner.Dsl.Mapping.dll" #>

Also, by default the T4 template generates an output file with a .txt extension. I’m going to stick with this to keep the example simple, but more usually, you’ll want something more meaningful such as .cs or .aspx. If so, change the output directive:

<#@ output extension=".cs" #>

Finally, you need to hook your template up to your NHibernate model, using a NHibernateModel directive. I’m going to assume we have a file called StoreModel.nhmodel, so my directive looks like this:

<#@ NHibernateModel processor="NHibernateModelDirectiveProcessor"
                    requires="fileName='StoreModel.nhmodel'" #>

Now everything is ready, we can start to generate some code.

Populating the template

For this simple example, my template is just going to generate a list of the entities in the model, in plain text format. (I dunno, maybe so you can print it out extra big so marketing can understand it.) This is a job for a simple foreach loop over the collection of entities, generating the name each time. So my template body looks like this:

Entities in model:
<#
  foreach (/* HOW DO I GET THE LIST OF ENTITIES? */)
  {
#>
* <#= /* HOW DO I GET THE ENTITY NAMES? */ #>
<#    
  }
#>

As you can see there are a couple of things I need to figure out about working with the NHibernate model. The first is how to get the list of entities. Well, thanks to the NHibernateModel directive, the template contains a member variable called Model which represents the NHibernate model. The model has an Entities collection which we can iterate over, so that solves that problem. The second thing is how to get an entity’s name. It turns out that the Entities collection contains Entity objects, and Entity defines a Name property. So that’s sorted too. Here’s the final template body:

Entities in model:
<#
  foreach (Entity entity in this.Model.Entities)
  {
#>
* <#= entity.Name #>
<#    
  }
#>

What are these Entity objects and how am I meant to know about them?

Note that the Entity objects in the NHibernate model aren’t instances of objects materialised from the database. They are the entity definitions on the designer. For example, if a model defines Customer, Product and Order entity classes, then the Model.Entities collection will contain three Entity objects corresponding to these three classes. Everything we’re talking about in this post is happening in the so-called ‘metamodel’ — the way the designer talks about NHibernate models, not about live NHibernate objects.

The bigger question though is how I knew that Model had an Entities property and that Entity had a Name property. Where is this stuff documented? Well — ahem — it isn’t. For the time being, you need to ask in the forums, or work it out for yourself. Fortunately, it’s usually pretty easy to guess. For collections, go to the NHibernate Model Explorer (View > Other Windows > NHibernate Model) and look at the folder names. Those are normally your collection names. For scalars, go to the Properties window and look at the setting names. Those are normally your property names. (Again, by ‘property’ I mean a property of the metaobject, not one of the properties you define as part of your domain model. So Entity has properties like Name, TableName, Visibility, etc.) In some cases, the display name doesn’t quite match the class or property name, in which case try looking at the element or attribute name in the .nhmodel file. Be prepared for a bit of exploration, and a bit of trial and error!

Trying it out

Okay, I’ve written my template, so now I’ll add some entities to my model and… nothing happens! Well, one annoying feature of T4 templates is that they don’t automatically re-run when the model changes. You need to choose the Transform All Templates button in the Solution Explorer toolbar to make them re-run. When I do this, the .txt file is regenerated and it contains the output we’d expect:

Entities in model:
* Customer
* Order
* Product

Obviously, this is a simplistic and unrealistic example. (That’s why I think it’s a great fit for marketing.) But using T4 you can generate C# or VB files, ASP.NET files, you name it — the sky’s the limit. If you’ve got a cool idea, download the NHibernate Designer for free and try it out!

Leave a Reply

Archives

Join our mailer

You should join our newsletter! Sent monthly:

Back to Top