You may have seen that NH 3.2 is out in the wild and being scarcely used due to its significant lack of documentation verbose enough to make any kind of sense. I have been on an uphill struggle trying to figure out how much of it works comparative to my previous use of NH 3.1 with a Fluent NHibernate configuration. This isn’t a limitation to the framework, it’s just because there aren’t many examples out there yet so hopefully this post will clear up a few things on how to set your environment up as well as having more complicated mappings.
As you may know, NH 3.2 has a fluent-like mapping which isn’t actually fluent (it uses ConfORM), there has been a mixed reaction from the community in regards to this, some saying it’s too heavy-weight for the NH framework and should be kept in its own library. From the examples I’ve seen of the new mapping configuration I think it’s brilliant for a number of reasons.
There is barely any documentation whatsoever in regards to this, so beware. My environment was mainly written from scratch with some inspiration from various areas, so it may seem a little weird to you, but it fit the needs of applications I have developed quite well. I’ll give the entire scope so you can understand. There’s a number of key files that make up my architecture giving the overall picture. Don’t worry for now, I’ll cover these in more detail later on.
Utils
Repositories
I also use AutoMapper to map my models to view models and vice versa.
The Mappings.cs file is the most important class here as it’s used to set up all of the mappings. I’ve only actually worked with two entities so far, however they’re going to be getting quite complicated as they’re self-referential and have virtual mappings (entities which don’t exist at the DB-level). In my case all of my mappings are set up in this single file, but in previous projects I’d have a class per entity mapping (that is, derivations of a class may exist in the same mapping class). Because of the matching against the XML mapping configurations you can use your prior knowledge in these files.
This file begins and ends transactions. There’s pro’s and con’s to this implementation, and I’ve actually weighed up a few. Some people prefer to explicitly open and close their sessions, you can do this in languages such as C# by using “using” statements. My implementation was a mixture of other solutions I had seen, when an entire web request finishes, that’s when the session is committed to the database. This does run the risk that if your presentation layer for some reason fails unexpectedly then it may mean the session didn’t complete. This may seem illogical but to the end-user it may make sense “I didn’t see something finish therefore it can’t have completed”.
This file also creates my session factory like so:
gist id=1133791
Be very careful as to what “SchemaAction” you use, otherwise you could end up deleting your data when new sessions are set up. I’ve found that updating key fields to have identity specifications don’t work using SchemaAutoAction.Update, but they work when creating new columns. It’s a bit buggy, so you may want to stick to migrations until they improve this functionality.
To set the mapper up you first instantiate a ModelMapper instance and then use this to “do stuff”. To be honest, the possibilities are quite endless, and it’s all dependent on your DB structure. Let’s take a full example to start with:
gist id=1133812
This is very simple, and there’s a few oddities. I specify the column because by default it doesn’t use this convention, so you have to explicitly state it. The identity generator doesn’t work if you add it after the schema has been created, prompting me to drop and re-create my schema quite a lot. It’d be easier if you added this and also added a migration, but always make sure you watch the issued SQL statements to ensure the updates to your DB have been issued. There’s likely a very good reason for this, because in some circumstances data can be damaged or lost during the update so it’s better if you run the migrations yourself. Here’s a slightly more complicated example:
gist id=1133801
And finally, a fuller example:
gist id=1133804