NHibernate is great, (no doubt about it) but every time I was supposed to work with it, the fact that I had to manually type in all those xml configuration entries was something I really didn’t like at all.
The most important complains I personally have on NHibernate configuration files are:
- It is error prone
- Errors in configuration file can be hard to trace
- It is not refactoring friendly
- It is not C#, it is XML
I believe that the most important reason why NHibernate is not more widely adopted by general DEV population is exactly the “Java XML configuration” PIA feeling you have while working with it.
Great news for all of us from that group: NHibernate is possible to be used WITHOUT configuration files!
Who, what and where?
Jeremy Miller coded initial bits of the Fluent NHibernate project and then with couple of guys more bring the project to Google code and they started finalizing it. OSS rules!
So, if you go to you would see names of other project members together with the simple code illustrating the goal fluent nhibernate project tries to achieve.
As with the most OSS projects, to get the source code of FNH, download it from Subversion trunk located at http://fluent-nhibernate.googlecode.com/svn/trunk/
Solution file consist of couple of projects:
- LIb solution folder contains DLL you would be using in your application.
- Test project containing a bunch of unit tests which you can use as starting point to get detail understanding on how the things works.
- Quick start project which highlights most important concepts you need to start using NHibernate
Note: Project is initially built with NHibernate 2.0 which collides with (using NHibernate 2.1) so I updated FNH project references to use 2.1 too
Fluent NHibernate in action
Solution project structure
In this blog post, I will use the same example used in his NHibernate chapter so you can compare outcome of my blog post sample it with how it looked in his book (with the configuration files in place).
Solution file of today’s example contains 3 projects:
- BusinessLayer (“Domain”) Contains definitions of entities which we use in modeling business use cases. Important to be mentioned here is that BusinessLayer project doesn’t have any reference to neither other projects of this solution nor the “3pty dlls” such is NHibernate.dll
- NHConfigMappings (“Mapping project”) Contains ORM mapping definitions which enables nhibernate to persist to relational DB domain entities
- NHCongigMappings.Test
Contains test fixture illustrating how mappings should be consumed and how nhibernate engine could be initialized without any xml configuration files
(Source code used in today blog post can be download from )
Domain project
As you can see, it is very simple sample where we have entity customer class containing “embedded” Address value object and referencing the list of reference persons customer contacted.
Same diagram given in code would look like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System; using System.Collections.Generic; namespace CustomerConfiguration { public class Customer { public virtual Guid Id { get ; set ; } public virtual string CustomerNumber { get ; set ; } public virtual string Name { get ; set ; } public virtual Address CustomerAddress { get ; set ; } public virtual IList<REFERENCEPERSON> ReferencePersons { get ; set ; } } } |
Address type will look like this:
1 2 3 4 5 6 7 8 9 10 | namespace CustomerConfiguration { public class Address { public virtual string Street { get ; set ; } public virtual string PostalCode { get ; set ; } public virtual string Town { get ; set ; } public virtual string Country { get ; set ; } } } |
And ReferencePerson type would look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 | using System; namespace CustomerConfiguration { public class ReferencePerson { public virtual Guid Id { get ; set ; } public virtual string FirstName { get ; set ; } public virtual string SurName { get ; set ; } } } |
As you can see from the code above, NHibernate allows us fully software development: no special attributes, no special base class or interface…
Mapping project
Once we have domain logic defined, we need to provide information on how NHibernate should map our classes with appropriate DB entities: tables and columns.
For my example DB would look like this:
As you can see, although in my code I have separate Address class I don’t have it in DB. Instead I have it embedded in Customer table as last 4 columns. Also, table names in DB are in plural form while names of classes are in singular form.
Another small difference here is that in ReferencePerson class has a LastName property while DB has column SurName.
Mapping ReferencePerson
I won’t throw in here example of how that would look if I would use XML configuration file, because the whole point is to forget that ASAP (In case you want to see it, check it out )
In order to define NHibernate mapping, in FNH you need to create a mapping class for each one of entities (which is something ).
That mapping class should inherit from ClassMap<T> class in order to get access to FHN members providing programmatic access over configuration settings
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | using CustomerConfiguration; using FluentNHibernate.Mapping; namespace NHConfigMappings { public class ReferencePersonMap : ClassMap<ReferencePerson> { public ReferencePersonMap() { TableName = “ReferencePersons”; Id(x => x.Id).GeneratedBy.GuidComb() .WithUnsavedValue(“00000000-0000-0000-0000-000000000000”); Map(x => x.FirstName).WithLengthOf(50).CanNotBeNull(); Map(x => x.LastName,”SurName”).WithLengthOf(50).CanNotBeNull(); } } } |
Main advantage of is that it produces code with good readability, which I believe we can see from code snippet above.
In a class constructor, I am defining:
- What is the name of data table where the class will be persisted. In my example table name and class name differs so I had to define it here, but I think it is good practice to define it always, even they are implicitly the same by the default
- Which class property should be used as populating table PK. In example I took I am using ReferenceMap.Id property where NHibernate generate its value using value as performance effective type of GUID values. At the end I defined how unsaved value is looking like so NHibernate would be able to deduct how the class should be persisted (insert or update)
- That the FirstName property should be mapped to the column with the same name where the column length is 50 characters and null values are not allowed
- That the LastName property should be mapped to the column named “SurName” with the maximum length of 50 characters without null values being allowed
In my opinion main advantages here are that the configuration code is human readable and refactoring friendly (if I ever do changes on ReferencePerson class mapping file will be broken so we have “type safe” configuration settings)
Mapping Customer
Customer class mapping definition is stored in CustomerMap (implementing the ClassMap<Customer> class looking something like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | using CustomerConfiguration; using FluentNHibernate.Mapping; namespace NHConfigMappings { public class CustomerMap : ClassMap<Customer> { public CustomerMap() { TableName = “Customers”; Id(x => x.Id).GeneratedBy.GuidComb() .WithUnsavedValue”00000000-0000-0000-0000-000000000000”); Map(x => x.Name).WithLengthOf(50); Map(x => x.CustomerNumber).WithLengthOf(50); HasMany<ReferencePerson>(x => x.ReferencePersons) .Access.AsProperty() .AsBag().WithKeyColumn( "CustomerId" ) .Cascade.All(); Component<Address>(x => x.CustomerAddress, m => { m.Map(x => x.Street).WithLengthOf(100); m.Map(x => x.PostalCode).WithLengthOf(6); m.Map(x => x.Town).WithLengthOf(30); m.Map(x => x.Country).WithLengthOf(50); }); } } } |
In a class constructor, I am defining:
- The name of table to which this class map
- Customer.Id as primary key containing guid value
- Customer.Name is mapped to the Name nvarchar(50) column
- Customer.CustomerNumber is mapped to the CustomerNumber nvarchar(50) column
- Customer class contains collection of ReferencePerson instances stored in Customer.ReferencePersons propertywhich should be mapped in separate table (AsBag()) where role of FK will be performed by ReferencePerson.CustomerId
and with cascading of events (Insert of Customer will result with Insert of ReferencePerson etc)
- Customer contains property CustomerAddress of type Address as embed value where
- Address.Street is nvarchar(100) column
- Address.PostalCode is nvarchar(6) column
- Address.Town is nvarchar(30) column
- Address.Country is nvarchar(50) column
Once again, take a look at the class above. I have just described something which looks like typical use case we face in real world with something which (IMHO) has very high readability and it is easy to be written
Unit testing fluent nhibernate mappings
In order to present how those mappings should be used I wrote unit test project which will present:
- how this mappings are to be used
- how to configure nhibernate itself without the need for hibernate.cfg.xml file
For the purpose of this test I choose MS Test just for kicks (although I am mostly using MBUnit )
How to initialize nhibernate without hibernate.cfg.xml
Due to the fact that initializing nhibernate engine is slow, I am initializing it once per text fixture and in test fixture of this example nhibernate initialization routine in case of fluent nhibernate is a 5 step procedure:
- Initialize type implementing IPersistenceConfigurer (MSSqlConfiguration, SQLLiteConfiguration, PostgreSQLConfiguration are currently supported)
- use instance of that type (in my example instance of MSSqlConfiguration) to preset properties of NHibernate.Configuration instance
- create instance of FluentHibernate.PersistenceModel type
- use that instance to load the assembly containing mappings
- use that instance to inject mappings to nhibernate configuration instance
At the end of configuration sequence I have operational NHibernate configuration instance which I use to create session factory which I then store as a class field.
Once I have that SessionFactory field in place, each one of the test methods just uses it to create a session needed.
Let’s take a look at how this initialization routine could look in code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | private static ISessionFactory _sessionFactory; [ClassInitialize] public static void FixtureInit(TestContext testContext) { // initialize persistance configurer IPersistenceConfigurer persistenceConfigurer = MsSqlConfiguration .MsSql2005 .ConnectionString.Is( “Data Source=.SQL2008;Initial Catalog=NHibernateBlog;" + "Integrated Security=True”) .ShowSql(); // initialize nhibernate with persistance configurer properties Configuration cfg = persistenceConfigurer .ConfigureProperties( new Configuration()); // add mappings definition to nhibernate configuration var persistenceModel = new PersistenceModel(); persistenceModel.addMappingsFromAssembly (Assembly.Load(“NHConfigMappings”)); persistenceModel.Configure(cfg); // set session factory field which is to be used in tests _sessionFactory = cfg.BuildSessionFactory(); } |
I think code above is simple enough (thanks to FNH) that it doesn’t need any extra explanations about its concrete implementation.
Nhibernate unit test method
Now when we have that session factory up and going, we would make only a simple test where we will create a new customer and try to store it in DB.
That test code could look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | [TestMethod] public void ReferencePerson_Create_ShouldCreateRowInDb() { var customer = new Customer { Name = “John Doe”, CustomerNumber = “12345”, CustomerAddress = new Address { Street = “1st Mayson Street”, PostalCode = “01754”, Town = “Maynard”, Country = “USA” }, ReferencePersons = new List<ReferencePerson> { new ReferencePerson { FirstName = “Nikola”, LastName = “Malovic” } } }; ISession session = _sessionFactory.OpenSession(); Guid id=(Guid)session.Save(customer); session.Flush(); session.Evict(customer); var customerDB= session.Get<Customer>(id); Assert.IsTrue( customerDB.Id == customer.Id && customerDB.Name == customer.Name && customerDB.CustomerAddress.Street == “1st Mayson Street” && customerDB.ReferencePersons[0].FirstName == “Nikola”); } |
At the beginning of the test method I create a new customer instance with CustomerAddress data and single ReferencePerson instance in ReferencePersons.
Then I use the sessionFactory created in test fixture set up, and create a session which then I use to persist customer instance. As a result of that persistence method call I am getting customer identity value used as PK value in DB.At the end of that persistence code I just flush the session in order to commit the changes.
Now when (hopefully) our customer is saved I need to test that and the usual way of testing save is to try to load the data from DB. That’s why I remove the customer instance from NHibernate Identity Map “cache” so I won’t get results from memory and then I am trying to retrieve data using the identity value I retrieved during persistence.
With the retrieved customer data I do just quick value check (in real world test this check would look different).
Test will pass therefore if retrieved data will match the data of customer instance created in this test.
Running the test
Once I run the test, I got successful test
And fast look at the DB shows that data are persisted
Test passed!
Conclusion
Purpose of this blog post was to present a way of using NHibernate different then the standard xml configuration approach most of people use right now working with NHibernate.
I hope you can see for yourself that it is VERY possible to use NHibernate without a single configuration file on very DEV friendly and intuitive way.
The example I presented here is just tip of the iceberg so I strongly encourage you to sync Fluent NHibernate source code and play with quick start and test projects.
Here are also some links you can check out too:
Happy Hibernating!