NHibernate for Entity Framework Developers: Part 1 – Fluent NHibernate

The approach to managing persistent data has been a key design decision in every software project we’ve worked on. Given that persistent data isn’t a new or unusual requirement for .NET applications, you’d expect to be able to make a simple choice among similar, well-established persistence solutions. Each of the competing solutions has various advantages and disadvantages, but they all share the same scope and overall approach.

Having said that, making the right decision requires a fairly good knowledge of the ORM solutions currently available for .NET. In other words, if all you know is one ORM and one only, then you won't have much of a choice in there, you always have to go with the only framework that you know of and sometimes it might not be the best solution for your specific project. Entity Framework could be a viable option, an approach to persistence, proposes to provide a ORM solution with the full commercial support and backing of Microsoft. But is that really enough reason for us to simply ignore just about everything else?

What is NHibernate and Why Should You Care?

NHibernate is an ambitious open source project that aims to be a complete solution to the problem of managing persistent data in .NET. NHibernate is a .NET port of the very popular and successful Java Hibernate library and is one of the most mature, powerful ORM frameworks available in .NET today, an important option and one that you shouldn't ignore.

What is the Goal of This Post?

From my experience with the .NET user community, I know that the first thing many developers (especially those with a history of using MS tools and frameworks like EF) say when it comes to NHibernate is that it's a sophisticated framework and has a steep learning curve. In this series of posts I'll walk you through the process of building a project with NHibernate and will show how you can leverage your EF knowledge to get up and running with NH as quickly and easily as possible.

This writing is not a debate on EF vs. NHibernate, nor is a comparison to show which one is better than the other. I'll just present the advantages and drawbacks of the two approaches to you and will show their solutions for various persistence problems. My hope is that at the end it gives you an insight to conclude which one is a better persistence solution for your specific project.

A Note For Those Who Never Worked with Any ORM Before

Keep reading! The title of this series might be a bit misleading as I don't assume any knowledge of EF when explaining NHibernate, of course being familiar with one ORM solution like EF would help but is absolutely not a requirement so with a little extra effort, you can learn NHibernate just like the EF developers.

Your First NHibernate Project

Open your Visual Studio and create a new Console Application project. Before you can start coding your first NHibernate application, you need to reference NHibernate binaries. NHibernate 3.1.0.GA can be downloaded from here. Download and extract the zip file to some location on your drive. The next step is to reference the required binaries in your new project. To do this, follow these steps:
  1. Right-click the project and select Add Reference...
  2. Click the Browse... button and navigate to the folder where NHibernate binaries are extracted.
  3. Open Required_Bins folder and select NHibernate.dll. Click OK to add this reference to your project.
  4. Right-click again on the the project and select Add Reference... and navigate to the folder where NHibernate binaries are extracted.
  5. This time open Required_For_LazyLoading folder and then Castle folder.
  6. Add a reference to NHibernate.ByteCode.Castle.dll.
Now that your solution is set up, you’re ready to start coding your first NHibernate application!

Creating a Domain Model

Just like my other posts on EF Code First, this post takes a top-down approach; it assumes that you’re starting with a domain model and trying to derive a new SQL schema but this time with NHibernate. When you’re using NHibernate, entities are implemented as POCOs, a back-to-basics approach that essentially consists of using unbound classes in the business layer which leads to the notion of persistence ignorance in our applications. This results in entities with less coupling that are easier to modify, test, and reuse. EF also supports this pattern starting from its second version (aka EF 4.0).
The following shows the POCO classes that form the object model for this domain:
public class User
{
    public User()
    {
        Items = new List<Item>();
    }
 
    public virtual int UserId { getprivate set; }
    public virtual string Name { getset; }
    public virtual string Username { getset; }
 
    public virtual Address Address { getset; }
    public virtual IList<Item> Items { getset; }
 
    public virtual void AddItem(Item item)
    {
        item.Seller = this;
        Items.Add(item);
    }
}
 
public class Address
{
    public virtual string Steet { getset; }
    public virtual string City { getset; }
    public virtual string ZipCode { getset; }
}
 
public class Item
{
    public Item()
    {
        Categories = new List<Category>();
    }
 
    public virtual int ItemId { getprivate set; }
    public virtual string Name { getset; }
    public virtual double Price { getset; }
 
    public virtual User Seller { getset; }
    public virtual IList<Category> Categories { getset; }
}
 
public class Category
{
    public Category()
    {
        Items = new List<Item>();
    }
 
    public virtual int CategoryId { getprivate set; }
    public virtual string Name { getset; }
 
    public virtual IList<Item> Items { getset; }
 
    public virtual void AddItem(Item item)
    {
        item.Categories.Add(this);
        Items.Add(item);
    }
}
The POCO classes are pretty straight forward, except you might wondering what the AddItem methods are for in there, for now, think of the code in the AddItem (a convenience method) as implementing a strong bidirectional association in the object model.

How Mappings are Specified in NHibernate?

Just like EF, NHibernate gives you different ways to specify mappings for your persistent classes. You can use XML files, CLR attributes or Fluent API.
  • Mapping using XML
  • The ability of mapping classes with XML is what NHibernate inherits from Hibernate, where usually each persistent class has an XML mapping file ends with the .hbm.xml extension and is embedded in the same assembly as the mapped class file. This is analogous to an EF's Edmx file but unlike Edmx files, these HBM mapping documents are lightweight, human readable, easily hand-editable and can be easily manipulated by version-control systems. Although Visual Studio comes with a designer support for Edmx files, but the problem is that this support is somewhat limited and you sometimes have to drill down to the underlying XML file to define your desired mapping or behavior, examples like creating a TPC mapping or defining QueryViews. I personally didn't find editing the raw XMLs in Edmx files (and dealing with an Edmx file in general) a fun practice and I think this is a common feeling throughout the community as we see more and more developers are leaning toward Code First development to keep their projects away from an Edmx file.
  • Attribute-oriented Mapping
  • Alternatively, you can use CLR attributes defined in the NHibernate.Mapping.Attributes library to provide all the information NHibernate needs to map your classes. This is comparable to the new attributes that the latest release of EF (EF 4.1) provides in System.ComponentModel.DataAnnotations namespace which you can use to map your classes when doing EF Code First development except that EF annotations are not complete and you often have to resort to fluent API to do the mappings (Examples like creating a TPC mapping, customizing a TPH mapping, specifying cascade deletes on associations or customizing the mapping for a many-to-many association.).
  • Fluent Mapping
  • Fluent mapping is based on a Fluent Interface that allows you to map your entities completely in code, with all the compile-time safety and refactorability that it brings. Just like the fluent API in EF Code First, Fluent NHibernate project provides an alternative to NHibernate's standard XML mapping files. As a result, rather than writing XML documents, you write mappings in strongly typed C# (or VB) code. It's even has a concept called Auto Mapping which is a mechanism for automatically mapping all your entities based on a set of conventions. This is very similar to the EF Code First as they both follow the convention over configuration principle. In this post we use Fluent NHibernate to map our persistent classes since this allows for easy refactoring, improved readability and more concise and elegant code. More importantly, if you used Code First fluent API before, you'll find this approach very familiar.

Adding Fluent NHibernate to the Project

Fluent NHibernate is a separate open source project that needs to be referenced in your project before you can start using its fluent interfaces to map your persistent classes. You can download the binaries from here. Once you've got a copy on your local machine, right-click the project and select Add Reference... and then reference the FluentNHibernate.dll assembly which is inside the extracted folder from the zip file you downloaded.

Mapping Entities and Components

In EF Code First, we use EntityTypeConfiguration class to define a mapping for an entity. We derive from this class to create a mapping, and use its constructor to control how our entity is persisted. Fluent NHibernate has the same approach except that it differs between an entity and a value object in essence that if you are mapping an entity you'd use ClassMap and if you are mapping a value object you'd use ComponentMap class. The reason for this naming is because NHibernate uses the term component for a user-defined class that is persisted to the same table as the owning entity. A Component is the exact same concept as a Complex Type in EF: an object that has no individual identity. The following code shows how to register the Address class as a component as well as how to specify UserId as the object identifier:
class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Id(u => u.UserId);           
        Component(u => u.Address);
    }
}

Associations in Entity Framework and NHibernate

As you may know, foreign keys in the first release of EF were not exposed on entities, something we know by the the name of independent associations. These associations were managed which means they had their own independent entry in the ObjectStateManager where each entry (of course) has its own EntityState. These independent associations make a few things such as N-Tier and concurrency really difficult. For example, concurrency checks were performed on relationships independently of the concurrency checks performed on entities, and there was no way to opt out of these relationship concurrency checks. The result was that your services must carry the original values of relationships and set them on the context before changing relationships. Because of this and a few other problems, these associations eventually became deprecated in the second release of EF and a new type of association called foreign key associations has been introduced where foreign keys were exposed in the persistent classes along with their related object references (aka navigation properties). The concurrency problem has been solved because now the relationship is simply a property of the entity, and if the entity passes its concurrency check, no further check is needed. Now you can change a relationship just by changing the foreign key value.

I have mixed feelings about these foreign key associations. On the one hand, it's not managed anymore and doesn’t expose us to all the problems of independent associations but on the other hand, foreign keys are part of the impedance mismatch problem and should not be in the object model. They add noise to the persistence classes and they even introduce some new problems. For example, having foreign keys as well as object references for relationship navigation presents the problem of two different artifacts representing one relationship – this introduces complexity and now you have to make sure that you keep these two in sync.

On the other hand, the NHibernate association model is interesting. Foreign keys correctly don't need to be part of the entities but at the same time NHibernate doesn’t "manage" persistent associations. It's kind of the best of two worlds approach. In NHibernate, if you want to manipulate an association, you must write exactly the same code you would write without NHibernate. If an association is bidirectional, both sides of the relationship must be considered. As you can see in the model, the Employee class, for example, doesn't reflect the ProductId foreign key from the database. Next, you'll see how associations are mapped in NHibernate.

Associations in NHibernate are Directional

It’s important to understand that NHibernate associations are all inherently unidirectional. As far as NHibernate is concerned, the association from Item to User is a different association than the association from User to Item. To EF developers, this might seems strange; I’ll merely observe that this decision was made because unlike EF, NHibernate objects aren’t bound to any context. In NHibernate applications, the behavior of a nonpersistent instance is the same as the behavior of a persistent instance.

Because associations in NHibernate are directional, we call the association from Item to User a many-to-one association (many Items sold by one user, hence many-to-one). You can now conclude that the inverse association from User to Item is a one-to-many association. The following shows the mapping code with Fluent NHibrenate for the Item entity:
public class ItemMap : ClassMap<Item>
{
    public ItemMap()
    {
        Id(i => i.ItemId);
        Map(i => i.Name);
        Map(i => i.Price);
 
        References(i => i.Seller)
            .Column("UserId")
            .Not.Nullable();                
    }
}
The References method creates a many-to-one relationship between two entities. So far we have created a unidirectional many-to-one association. The column UserId in the Item table is a foreign key to the primary key of the User table.

Making the Association Bidirectional

Now let's have a look at the mapping for the User entity as the other end of the User-Item association. Here we use the HasMany method to create a one-to-many association from User to Item:
public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Id(u => u.UserId);
        Map(u => u.FullName).Length(50);
        Map(u => u.UserName).Not.Nullable().Unique();
 
        Component(u => u.Address);
 
        HasMany(u => u.Items)
            .Cascade.All()
            .Inverse()
            .KeyColumn("UserId");
    }
}
The mapping defined by the KeyColumn method is a foreign-key column of the associated Item table. Note that we specified the same foreign-key column name in this collection mapping as we specified in the mapping for the many-to-one association. Now we have two different unidirectional associations mapped to the same foreign key. At this point, all we need to do is to tell NHibernate to treat this as a bidirectional association. The Inverse method tells NHibernate that the collection is a mirror image of the many-to-one association on the other side and we are done.

Mapping a Many-to-Many Association

HasManyToMany method creates a many-to-many relationship and we use it to map the association between Item and Category entities. In NHiberbate, a bidirectional association always requires that you set both ends of the association and a many-to-many association is not an exception:
public class CategoryMap : ClassMap<Category>
{
    public CategoryMap()
    {
        Id(c => c.CategoryId);            
        Map(c => c.Name);
                        
        HasManyToMany(c => c.Items)
            .Cascade.All()
            .Table("ItemCategory");
    }
}
public class ItemMap : ClassMap<Item>
{
    public ItemMap()
    {
        Id(i => i.ItemId);
        Map(p => p.Name);
        Map(i => i.Price);
                        
        References(i => i.Seller)
            .Column("UserId")
            .Not.Nullable();
            
        HasManyToMany(i => i.Categories)
            .Cascade.All()
            .Inverse()
            .Table("ItemCategory");
    }
}
When you map a bidirectional many-to-many association, you must declare one end of the association using Inverse method to define which side’s state is used to update the link table. I chose the Item entity to be the inversed end of this many-to-many association. This setting tells NHibernate to ignore changes made to the Categories collection and use the other end of the association— the items collection —as the representation that should be synchronized with the database.

NHibernate Configuration and Schema Generation

The object model and its mappings are ready and now all we need to do is to wire them to NHibernate. Fluent NH can help us with this as well since it provides an API for completely configuring NHibernate for use with your application, all in code. The following shows how:
ISessionFactory factory = Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2008
                .ConnectionString(c => 
                        c.FromConnectionStringWithKey("SQLExpress")))
        .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Program>())
        .ExposeConfiguration(config => 
        {
            SchemaExport schemaExport = new SchemaExport(config);
            schemaExport.Drop(truetrue);
            schemaExport.Create(truetrue);
        })
        .BuildSessionFactory();
Fluently.Configure starts the configuration process. The Database method is where you specify your database configuration using the database configuration API. ExposeConfiguration is optional, but allows you to alter the raw Configuration object. BuildSessionFactory is the final call, and it creates the NHibernate SessionFactory instance from your configuration. We'll take a closer look at ISessionFactory and other NHibernate's core interfaces in the next post.

As you may have noticed, this code also generates the DDL from the object model and executes it against the target database but with one caveat: You need to manually create the database yourself before running this code since NHibernate will not create the database for you. Like the class name suggests (SchemaExport), it only creates the schemas in the database. After creating the database, you can run this code as many times as you want, as it is designed just like EF Code First's DropCreateDatabaseAlways strategy.

SQL Schema

The presented object model will result in the creation of the following schema in the database:

Source Code

Click here to download the source code for the project that we have built in this post.

Summary

In this post, we take a high-level look at NHibernate and its mapping system by running a simple example. We also saw how to configure NHibernate with Fluent NHibernate, a technique similar to EF Fluent API which saves us from dealing with XML mapping files. This post sets the basis for the next part where we will focus more on the dynamic behavioral aspects of NHibernate, something that comes into play at runtime and we'll see how it differs from EF in that area.
* A QueryView is a mapping that allows you to override the default mapping for an entity and return a new read-only strong type. This way, you can get the benefit of a projection, but return an entity instead of an anonymous type which you can’t pass around from one method to another.

5 Comments

Comments have been disabled for this content.