Total votes: 2
Print: Print Article
Please login to rate or to leave a comment.
Published: 16 Apr 2009
Download Sample Code
In this second part Gabriel Schenker continues his overview of the NHibernate OR/M.
In the first part  of this article series I have introduced NHibernate and its sister project Fluent NHibernate. I have discussed the perquisites needed to start developing a NHibernate based application. Finally I have introduced a simple domain model which I then took as a base to implement. The first entity of this domain was then implemented and mapped. The unit test for the mapping was discussed.
In this second part I’ll continue to implement and map the remaining part of the domain.
Your very first NHibernate application series
Part 1 In this series of articles Gabriel Schenker want to show and discuss which pieces are needed to successfully write an application based on NHibernate and Fluent NHibernate.Part 2 In this second part Gabriel Schenker continues his overview of the NHibernate OR/M.Part 3 In this part of the series about NHibernate and its sister product Fluent NHibernate, Gabriel Schenker introduces the auto mapping feature of Fluent NHibernate.
Implementing and mapping the remaining domain objects
First let’s implement and map the Product class. This process is similar to the one used when defining and mapping the customer object. Let’s first have a look at the implementation of the product class
To keep our sample simple I have only implemented the most important properties. The mapping is straight forward and very similar to the mapping of the customer class in the first part of this article. So I don’t want to discuss the details again. Below you can see the implementation of the ProductMapping class
Again the unit test for the mapping is similar to the unit test of the customer mapping class. We can use the PersistenceSpecification helper class of the Fluent NHibernate framework to facilitate this task.
The PersistenceSpecification class offers a fluent interface to define the exact testing context. The mapping of an individual property can be tested with the aid of the CheckProperty method which expects as a first parameter a lambda expression of the property to map and as a second parameter a value which is assigned to the property during the test.
Certainly you might want to know what exactly is happing during the test. The easiest way to do this is to enable the logging of the SQL produced by NHibernate. This is very easy - we just have to change the configuration in the base fixture class as follows
The only thing we have changed is the .ShowSql() method call we have added in the SetupContext method of our FixtureBase class. When running the above unit test the following output is generated by NHibernate
Figure 1: Unit Test Session window of Resharper when running the product mapping unit test
As we can see the unit test creates an insert statement with the values provided and subsequently reloads the data written to the database with a select statement.
Now we come to a more interesting piece of the domain, the order and its order items. Let’s start with the OrderItem class. Here is its definition
Again for simplicity only the most important properties are implemented. Adding additional properties is straight forward and is left for the reader as an exercise. Below the mapping for this class is shown. Please note the new keyword References. With this keyword we define a many-to-one relation between an order item and a product. That is each order item has/references exactly one product whilst every product can be referenced by many order items (in different orders!). With the
.Not.Nullable() statement we declare that the reference to a product is mandatory (otherwise an order item is in an invalid state).
Note as well that the Id of the order item class is not mapped as a key. An order item is not an entity but rather a value object . It cannot exist on its own. An instance of an order item can only be defined in the context of an order. As such the Id of the order item is only an internally used index to provide a sort index for order items of an order. The Id of an order item has to be defined by the order object when a new order item is added to it.
The unit test for the mapping is shown below
Note how the reference to the product is checked with the CheckReference method. There is one problem though with this test. It fails. This is due to the fact that we have not defined when two instances of type product are the same. We thus have to override the Equals and the GetHashCode methods inherited from the Object base class. This can be done as shown below
An even better way would be to define an entity base class which implements these two methods. All domain entities would then inherit from this base class. You can find a detailed discussion about identity, equality and hash code in this  article.
Let’s define such a (generic) base class now from which all entities will then inherit
Now the product (as well as the customer, employee and order) class has to inherit from this base class as follows
Once we have defined equality for the product we can now re-execute the unit test and it will pass this time. When running the unit test the following output is produced
Figure 2: Result of the unit test verifying the mapping of the order item class
Note how Fluent NHibernate automatically inserts the product for us which is then referenced by the order item object.
The final piece is the implementation and mapping of the order class. The definition of the order class is given below
Note that it is very important not to expose the OrderItems collection as List<T> but rather as IList<T> (or even as IEnumerable<T>). Otherwise you will get a type cast exception.
The mapping of the order class can be seen here
Again we have two References elements in the mapping. An order has a many-to-one relation to a customer as well as to an employee (who records the order).
The new and interesting part here is the HasMany element. With it we can define a one-to-many relation. The order object contains a list of order items. The collection of order items belonging to an order are returned as a list. The index of the list is mapped to a column called ListIndex of the corresponding table in the database. The type of this column in the table is int. We could as well map the order items as a set or other (interesting) collection type.
The unit test which verifies the mapping is presented below
The above test is a bit lengthy since we have a lot of setup. We need products to be able to define meaningful order items. These products we have to explicitly save to the database. This is done with the aid of the session object. Now we can define order items which reference these products. We also need a customer and an employee object. Having defined all these elements we can now verify or test the mapping of the order entity.
Please note especially the
.CheckList(…) method that is used to verify the mapping of the order items list.
In part 2 of the article series on NHibernate and Fluent NHibernate I have continued to implement the remaining part of the domain. I have discussed the mapping of various forms of relations between different entities. For all mappings I have presented the code needed to verify the mappings.
In my next article I’ll show you how further refactor and improve the mapping of our domain model. I’ll then discuss the usage of conventions and finally show how we can use the auto-mapping capabilities of Fluent NHibernate to completely avoid the explicit mapping of entities. Stay tuned.
Installing Ruby to build Fluent NHibernate
To be able to compile the Fluent NHibernate project you need to install Ruby  on your system since Rake  is used as a build engine. Ruby is open source and thus free. The installation is quick and painless. It doesn’t take a lot of space on your hard disk neither. Ruby is very popular and powerful for things like writing build scripts. At the time of this writing version 1.9.1 is the official and recommended one.
Once you have installed Ruby you need some extra libraries for it. These additional libraries are called Ruby Gems and can be downloaded from the internet as well. In our case we don’t have to do it manually. The authors of Fluent NHibernate have prepared a batch file which automates this task for us. So please navigate to the root directory of Fluent NHibernate and locate the file InstallGems.bat. Double click this file and the necessary Gems will be downloaded from the internet and installed. When the Gems are installed (this can take several minutes, so please be patient) we are ready for our last step. Still in the root directory of Fluent NHibernate double click on the file build.bat. The project is compiled and all the unit tests are executed. If the build (including the tests) was successful you should find all artifacts (assemblies and the like) in the sub-folder build.
If you want to also download NHibernate then just create another directory on your file system, e.g.
c:\dev\NHibernate. Right click on this directory and choose the context menu item Checkout. Enter the following URL and click OK.
Now the complete source code is downloaded. This will take some time depending on the speed of your network connection. Once everything is downloaded you can build the project. Just follow the instructions in the file readme.txt in the nhibernate sub-folder.
Gabriel Schenker is a independent consultant, trainer, mentor and developer. He lives in Switzerland near to Zurich. His special focus is on practicing lean or friction-less software development. This includes practicing TDD, BDD and DDD. He is constantly advocating, promoting and supporting a cont...
This author has published 4 articles on DotNetSlackers. View other articles or the complete profile here.
Please login to rate or to leave a comment.