Sunday, 21 April 2013

Configuring NHibernate with TinyNH, the Simple NHibernate Infrastructure

TinyNH is a demo project and series of articles designed to help you get your project up and running with a simple solid NHibernate persistence infrastructure. See contents for a full list of articles.

Introduction

The previous article covered the implementation of your domain model entity classes. The next thing that you need to do is give NHibernate the information it needs about your object model and tell it how to map this from the database. To do this, we need to initialise a Configuration object.

Where Does NHibernate-specific Code Belong?

You first need to make a decision about where you want to locate the NHibernate-specific code in your solution. In TinyNH, we keep our project structure simple. Our entity classes live in the TinyNH.DemoStore.Core.Domain namespace and our NHibernate code is located in the “child” NHibernate namespace TinyNH.DemoStore.Core.Domain.NHibernate:


It is, of course, possible to use a separate project if you don't like the idea of your entities “knowing” about NHibernate.

ConfigurationBuilder

In keeping with  the Single Responsibility Principle, TinyNH uses a dedicated ConfigurationBuilder class, which creates the NHibernate Configuration. It’s just a simple class, which you can see below:


Please look at ConfigurationBuilder on github if you can't see the code in-line above.

There are two things to explore further here: a preference for configuration by code and a mechanism for overriding default configuration properties.

Prefer Configuration by Code instead of Configuration Files

There are a range of configuration properties available in NHibernate and, traditionally, these have been stored in configuration XML files or a section within your app.config / web.config (NHibernate originates from the Java world, I think somebody once wrote that Java is a DSL used to convert XML files into stack traces).

Configuration files are useful if you need to be able to change aspects of the configuration at runtime, for example if your application ran on a range of database platforms, then you would need to introduce configuration files to configure the “driver” and dialect “properties” for each deployment.

However, if you don’t need this flexibility, there are benefits to pushing as much NHibernate configuration as possible into code. In TinyNH, all configuration is done by code within our ConfigurationBuilder class and the only thing that is configured from the “outside” is the connection string. If we do it this way, we don’t need separate NHibernate configuration files, or a separate configuration section in our web.config or app.config file. This can be awkward to maintain if you have multiple applications in your solution. It also ties you down to a "static" configuration file and makes your code less testable.

Configuration Overrides

There are scenarios where we might want to make small changes to our standard NHibernate Configuration. One example is enabling certain features for testing and diagnostic purposes, such as asking NHibernate to maintain statistics about database activity or to log all SQL statements it executes using nice readable indented SQL.

Using a single ConfigurationBuilder and performing all configuration by code needn't restrict us when we do need to vary aspects of our configuration. ConfigurationBuilder's optional "customize" constructor parameter allows the NHibernate configuration to be customised on a per-application basis. For example, when we create a Configuration object for use in our automated tests, we enable a couple of useful features that we wouldn't want to have running as standard in a production environment:

Please look at DatabaseTests.cs on github if you can't see the code in-line above.

Class Mapping Options

TinyNH's main goal is to help you to put things in the right place. It doesn't prescribe any single approach to configuring your mappings.

For simpler projects, NHibernate’s built-in mapping by code API provides you with a nice concise way to configure your mappings. The ConfigurationBuilder in TinyNH sets up mappings using this mechanism, via a separate ModelMapping class. The properties of our entity classes are configured explicitly, with a few conventions handled by the BeforeMap[something] extension points.

How to do it

It's time to add the NHiberate configuration functionality to your solution:

  1. Copy ConfigurationBuilder.cs and ModelMapping.cs from TinyNH to a suitable location and adjust the namespaces as appropriate.
  2. Modify the configuration and mapping in line with your preferred approach to mapping and the structure of your domain model entities. 
Remember to start simple and consider mapping a single entity class to begin with.


Final Thoughts

You might be feeling a little short-changed here. You'll need to do most of the thinking around setting up your configuration and mapping yourself, all this article has done is told you where to put it! However, having a clearly identifiable "home" for your NHibernate configuration that isn't embedded deep within your application start-up code, or tied to specifically named configuration files has a number of useful benefits, which we'll explore in the future.

1 comment:

  1. This is a good read for computer enthusiasts. The text is organized with sub headings. It is somewhat coherent. The outlook is satisfactory enough for a tech blog.

    ReplyDelete