Thursday, 11 December 2008

I'm sure that lots of people is familiar with NHibernate and had a chance to work with it. I had a chance and I have to admit that it was a good time. But there are certain things which I hate about NHibernate like ... XML files, configuration, mappings ... to get it running tons of XML has to be produced.

Right, it's true that once this is done you don't have to go back there very often ... unless you want to do some refactoring. If you would like to rename some classes, move them to a different namespace or maybe rename some of the properties then you are in a big trouble ... Visual Studio and ReSharper will help you with refactoring of your code but you have to maintain XML files on your own.

Introduction to Fluent NHibernate

Apparently someone finally got pissed off and decided to change it ... goal was to get rid of all that maddening XML files. In other words, idea was to replace this:

In this form you can refactor your code as much as you like, it won't break your mappings. Your application is much more readable and maintainable. Thanks to Fluent NHibernate (FN) you can forget about XML files.

Quick Start Guide

We are still waiting for the first official release of Fluent NHibernate (FN) so at the moment the only option to get it is to use SVN client, check out the project and build dll on your own.

Having FluentNHibernate.dll you can simply add it to your project and start using it.

To make it easier I have prepared very basic web application which has FN set up, you can download it here. It uses popular AdventureWorks database.

Steps to get FN working:

First of all you need to configure NHibernate which includes general configuration (connection string, dialect, driver etc) and mappings. In terms of general configuration, you have two options:

configure NHibernate without any XML files

1: // of course, in real life, connection string should be externalized

Mappings, in this case my goal was to keep this example as simple as possible and elaborate it in future therefore for now only one table is mapped:

this is a POCO object representing a product:

1: publicclass Product

2: {

3: publicvirtualint Id { get; set; }

4: publicvirtualstring Name { get; set; }

5: publicvirtualstring ProductNumber { get; set; }

6: publicvirtualbool MakeFlag { get; set; }

7: publicvirtualbool FinishedGoodsFlag { get; set; }

8: publicvirtualstring Color { get; set; }

9: publicvirtualint SafetyStockLevel { get; set; }

10: publicvirtualint ReorderPoint { get; set; }

11: publicvirtualint StandardCost { get; set; }

12: publicvirtualint ListPrice { get; set; }

13: publicvirtual String Size { get; set; }

14: publicvirtualint DaysToManufacture { get; set; }

15: publicvirtual String ProductLine { get; set; }

16: publicvirtual String Class { get; set; }

17: publicvirtual String Style { get; set; }

18: publicvirtual DateTime SellStartDate { get; set; }

19: publicvirtual DateTime SellEndDate { get; set; }

20: publicvirtual DateTime ModifiedDate { get; set; }

21: }

and mapping:

1: public ProductMap()

2: {

3: // table name is different then class name

4: WithTable("Production.Product");

5:

6: Id(x => x.Id, "ProductID");

7:

8: Map(x => x.SellEndDate);

9: Map(x => x.ReorderPoint);

10:

11: Map(x => x.Name).WithLengthOf(50).Not.Nullable();

12: Map(x => x.ProductNumber).WithLengthOf(25).Not.Nullable();

13: Map(x => x.MakeFlag).Not.Nullable();

14: Map(x => x.FinishedGoodsFlag).Not.Nullable();

15: Map(x => x.Color).WithLengthOf(15);

16: Map(x => x.SafetyStockLevel).Not.Nullable();

17: Map(x => x.StandardCost).CanNotBeNull().CustomSqlTypeIs("money");

18: Map(x => x.ListPrice).CanNotBeNull().CustomSqlTypeIs("money");

19: Map(x => x.Size).WithLengthOf(5).Not.Nullable();

20: Map(x => x.DaysToManufacture).Not.Nullable();

21: Map(x => x.ProductLine).WithLengthOf(2);

22: Map(x => x.Class).WithLengthOf(2);

23: Map(x => x.Style).WithLengthOf(2);

24: Map(x => x.SellStartDate).Not.Nullable();

25: Map(x => x.ModifiedDate).Not.Nullable();

26: }

In this case table name is different then class name that is why I had to specify it but in general FN assumes that class name equals table name. The same approach is applied for properties and columns. Again you can specify that a column has different name then a corresponding property if necessary. Also it's not required to specify generator type for primary key column. FN checks property type and uses default one.

Testability - significant advantage is that you don't have to remember about keeping XML files up-to-date with your code and database schema, but also FN offers number of ways to facilitate creation of unit tests and integration test. I will cover that in a next post. (edit: post regarding integration tests)

I encourage you to keep an eye on this project. In a meantime you can start playing with the Fluent NHibernate by checking the sample web application.

4 comments:

It's nice you liked it :) If you liked, than also Sharp Architecture might interest you. It is a project that glues Fluent NHibernate with Asp.Net MVC, IOC container Castle Windsor and Nhibernate.Validator

Hi Aleks, I have seen Sharp Architecture before ... probably another interesting project, but as you know, we don't use ASP.NET MVC, at least not yet, therefore I decided to check only Fluent NHibernate for now.

On the other hand I would like to take a look on ASP.NET MVC soon so maybe I can check Sharp Architecture in the same time ;)

About Me

I have started as a developer and gradually got promoted to team lead, scrummaster and now technical project manager / product owner. My career path gives me deep overall technical knowledge as well as deep knowledge about digital marketing (SEO, Analytics, Content marketing, Social Media).