Adventures in .NET Software Craftsmanship!

NHibernate has been the ORM (Object Relational Mapper) of choice on practically all projects I have been involved in over the last couple of years and I have nothing but positive things to say about my personal experience with NHibernate. That being said, I do remember back in 2007 when I was faced with the task of evaluating NHibernate as a replacement for a brittle hand coded DAL (Data Access Layer) that there was scarcely any documentation or books for –true- beginner's. Obviously, the landscape has changed a bit since, there is a lot of documentation out there in the form of blogs and books that will guide you in the task of using NHibernate to its fullest potential but it is still very hard to find a good beginner’s guide.

“NHibernate 3 Begginers Guide” fills the need for a thorough beginner’s guide for NHibernate. The material is well presented and organized, and as with most books that are published by PACKT (http://www.packtpub.com/) the material is code and example driven which in my opinion fits best the way most developers learn these day’s.

A hidden gem in this book is Chapter 7 which provides a general introduction on how to monitor, test and profile you data access strategy. NHibernate’s design for testability is in my opinoin the key feature that sets it apart from other ORM’s in the .NET space.

ConclusionI would recommend this book for those learning NHibernate or thinking about choosing NHibernate for their data access technology as it answers most of the questions that you might have before getting up and running and building solid applications. As a bonus, the book also touches on some more advanced topics like what mapping strategy should I use and how to develop and implement a testing strategy for my data access code.

As promised, and in record time, the code and slides for my presentation on NHibernate 3.0 Alpha are now available for download. As usual, I would like to express my thanks to Justin Etheredge and Kevin Hazzard for hosting and allowing me to present at Richmond Code Camp 2010.2 (http://www.richmondcodecamp.org).

Disclaimer: This articles highlights a workaround not a best practice. In fact, if you are so inclined, please provide me with your feedback on how you would have solved this problem differently.

At a recent consulting gig a client’s IT department made the very common request that we store classic audit trail information in all database records. What that means, at least to me, is that every single record in the database is going to have a [CreatedBy], [CreatedDate], [UpdatedBy], and [UpdatedDate] fields. I found a lot of help on the internet on how to implement this by using NHibernate and its Event Model introduced (ported from Hibernate) in the 2.0 version.

Both articles are pretty much self explanatory and solve all the business requirements except one, and I quote “All dates in the audit database fields must be the Database Server Time not the Application Server Time”. Now this might sound like a simple requirement that can be solved this by defining custom SQL queries for insert, update and delete operations in the NHibernate mapping files but doing so will introduce the following problems:

1.- Writing custom xml mapping files defeats the purpose of using FluentNHibernate and its AutoMapping capability.

2.- Our integration testing strategy that relies on the use of SQLite would be become complex as we would have to define custom .hbm mapping files for testing and different ones for production ones that use T-SQL for SQL Server 2008.

My solution, albeit probably not a good one, was to define a named query for retrieving the Database Server Time from the application. The following is the code for registering that named query using the NHibernate’s fluent configuration API.

The key is to call the RegisterServerDateTimeMethod which registers the named query depending on the connection driver class settings name. Now to make the process of calling this named query easier I wrote an extension method for NHibernate’s ISession that looks like the following.

The following test illustrates how to use the Extension method. * Needless to say this test is very brittle and doesn’t really test much, but it gives me some peace of mind as it verifies that the .hbm file mapping syntax is valid.

As detailed in the FluentNHibernate website the 1.1 RTW was released last month! The main purpose of the release was to get everybody off the trunk and have the latest version of FluentNHibernate target the latest NHibernate build 2.1.2GA. Additionally, the release included a lot of new functionality and bug fixes that have been added by community members. At first glance there didn’t seem to be any changes that would break any existing applications, but as always with these type of things I managed to find a scenario where an existing project simply collapsed because of decisions made on the original design.

Trouble Scenario

While using 1.0RTM and the default auto mapping functionality, a class like the Budget class in the following snippet would result in the Id being mapped as the identifier, the Amount being mapped as a property and the AmountFormatted property would be ignored as it would be identified as a read only property. This behavior changes significantly in the 1.1RTW build where the default behavior is to map the AmountFormatted property producing a nasty error that stresses that no setter was found for this property, if indeed your intent is to map and persist the information in this read only property then you would have to define an access strategy for a backing field.

Solution
If you do not intent to persist the information in that read only property, one possible solution is to specify IAutoMappingOverride<T> classes for all entities that are being mapped in your system and manually specify each read only properties to be ignored. Needless to say that this is not the preferred migration path for a large application where we relied on the original auto mapping behavior and now have 30 or 40 entities that we would need to build specific overrides for. The more elegant solution is to use a new feature in 1.1RTW, the new AutoMappingConfiguration that allows you to define rules for types that are to be mapped and members of those types. So adding the following CustomAutoMappingConfiguration solved all my problems.

As promised the code for my presentation at the Norhern Virgnia (Nova) Code Camp is attached. For those of you who missed the presentation I will be presenting again later on this month at the CapArea.NET user's group. I want to congratulate Jeff Schoolcraft and the rest of the organizers for a very successful code camp and hopefully we will get to do it again during the spring.

The Author

Currently a Developer Extraordinaire at InfernoRed Technology based out of Northern Virginia. I have been architecting and building software solutions using Microsoft technology for the past 14 years. I was awarded a Microsoft MVP award for C# in 2007,2008 and 2010 and currently an active participant of the Microsoft MVP reConnect program. I am originally from the Dominican Republic, and the proud father of two beautiful daughters that make my life special. You can track me down on twitter (@hernandezrobert) and on this blog at http://www.overridethis.com.