By the time you read this, we’ll be off enjoying the long weekend, so consider this a message from the dusty past about that great question of the day: what’s new in this week’s nightly builds.
LightSpeed
WPF Elements
Web Workbench
NHibernate Designer
You know the drill — free editions from the Downloads page, full editions from the store. Enjoy!
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!
Ivan is off moonlighting as a luchador today, so its my turn to provide the weekly update. Its mostly been a week of bug fixes and working toward getting WPF Elements 5.1 out the door with a bunch of performance improvements and new features. Meanwhile we continued to beaver away on all the other products of course :) Here’s what’s new in this week’s nightly builds.
LightSpeed
NHibernate Designer
WPF Elements
Web Workbench
As ever, nightly builds of free editions are available from the downloads page, and of full editions from the store.
WPF Elements
LightSpeed
NHibernate Designer
Web Workbench
//* ww-expect "filename" comment)Nightly builds of free editions are available from the downloads page, and of full editions from the store. Enjoy!
LightSpeed
Web Workbench
NHibernate Designer
WPF Elements
All these updates are included in the latest nightly builds — free editions from the Downloads page, full editions from the store.