Nhibernate, ASP.NET MVC 3 and Ninject

In this post I said something about dependency injection and that we all should, well, inject dependencies. Why? To make our applications loosely coupled. In an ASP.NET MVC 3 application, I don’t want my Views to know what is in my persistence layer. Hell, I don’t even want my Controllers to have a notion. And I want to be able to change the Entity Framework with Nhibernate or DB4o.

And since I have this obsession with Nhibernate lately, this post is again about Nhibernate. And Ninject.

Wire up Nhibernate in ASP.NET MVC 3

A Nhibernate Session is very cheap and does not require too many resources. So, we’re setting up a session per web request, in Global.asax. The session opens when the request begins and closes when the request ends. I already blogged about that here. This also how Ayende demonstrates this in the Tekpub series.
Global.asax is also the place where we wire up Ninject. Download Ninject.Web.Mvc and Ninject from here rather than from Github, because strange things happen if you don’t.

Now, take a look at my very bloated Global.asax:

Sorry for that.

So, when we issue a webrequest, a Nhibernate Session is established. A Session in Nhibernate is the same as a Unit of Work. It’s also comparable with the Linq to SQL’s datacontext.
Now let’s create a PersonRepository interface:

[code language=”csharp”]
using System.Web;
using Concepts.Core;

namespace Concepts.Web
{
public interface IPersonRepository
{
IQueryable<Person> GetPersons();
}
}
[/code]

And implement the interface with Nhibernate:

[code language=”csharp”]
using System.Web;
using NHibernate;
using Concepts.Core;

namespace Concepts.Web
{
public class PersonRepository :IPersonRepository
{
private ISession _session;
public PersonRepository(ISession session)
{
_session = session;
}
public IQueryable<Person> GetPersons()
{
return _session.CreateCriteria<Person>().List<Person>().AsQueryable();
}
}
}
[/code]

Now the Dependency Injection trick. We’ll use Ninject to bind the IPersonRepository to our PersonRepository, and to bind the ISession to the method GetCurrentSession from Global.asax:

[code language=”csharp”]
using System.Web;
using Ninject.Modules;
using NHibernate;

namespace Concepts.Web
{
public class ConceptsNinjectModule : NinjectModule
{
public override void Load()
{
this.Bind<IPersonRepository>().To<PersonRepository>();
this.Bind<ISession>().ToMethod(x => MvcApplication.SessionFactory.GetCurrentSession());
}
}
}
[/code]

And now we can inject our HomeController with the IPersonRepository.. ! When we fire up our controller methods, Ninject sees that we implemented the PersonRepository, which uses Nhibernate. And this, ladies and gentlemen, is so cool, it hurts.

You can get the complete source code here.

Nhibernate Many-to-Many Mapping with extra attributes on the relationship

I dropped the Fluent from Nhibernate. I just wanted to experience the whole manual XML mapping thing. Well, it turned out not to be a bad experience at all.

Member registration app

I’m writing a member registration application. There are members and these members live on one or more addresses. Some addresses have more members. And on top of that, the relationship itself has some characteristics. Is it a postal address? Is it a temporary address?
This is the classical many to many relationship. How to map that in Nhibernate?

I decided to create two one-to-many relationships and a special relationship class. Here is the class diagram:

As you can see the PersonAddress class has some extra attributes for the relationship: there are two one to many relationships, from Address to PersonAddress and from Person to PersonAddress.

This is the Person class:

As you can see in line 13 I use the Iesi.Collections.Generic.ISet. It maps to an Nhibernate set (which is an IList). There should be an ISet interface in .NET Framework 4.0, but I need to investigate that further. For now, I’m using the ISet.

The Address class has a similar signature:

And then finally there is the PersonAddress class that maps the Person and the Address in a many-to-many relationship:

Object-relational impedance mismatch

Now we will use Nhibernate to solve the object-relational impedance mismatch which in itself is awesomely cool. Because, what is that thing with a RDBMS? Well, a relationship between two tables is defined in one table by adding a foreign key and then the relationship is bidrectional by default. In OOP, it does not work that way. If I add a collection of addresses as a property from a person, the address does not know anything about the persons that may live there. I have to create a collection of persons to the the address class as well (as I did in the above mentioned code). I have to, because I want to know on which addresses a person lives, but I also want to know which persons live on a certain address.
So here is how we map the Person class to the RDBMS:

Remember the ISet Addresses in the Person class? (virtual public Iesi.Collections.Generic.ISetAddresses { get; set; }). In this mapping file, I defined a set with the name Addresses. And that is how it maps. But the other stuff is also important:

  • inverse=true means, this side is the relationship owner in a bi-directional relationship. If I omitted inverse=true, then Nhibernate would try to execute two different SQL statements.
  • cascading: all-delete-orphan – when an object is saved, updated or deleted, check the associations and save/update/delete all the objects found. When an object is removed from the association and not associated with another object (orphaned), then also delete it. When the person object is deleted, the PersonAddress object will be deleted.
  • The keycolumn is PersonId, in the PersonAddress object. (It is the foreign key).
  • The one-to-many class is the PersonAddress class

This is how I would map the PersonAddress class:

Notice that PersonAddress has a many-to-one relationship with both Person and Address.

Address is, again, similar to Person:

There we go. So, the important things are:

  • inverse=true
  • one-to-many versus many-to-one
  • defining the key column
  • transitive persistence: know the lifecycle of your objects (set by the cascade attribute).

Creating the databasetables

Nhibernate has the possibility to create tables from the mappings.
First you need to create a database and the Nhibernate creates the tables. And the relationships. Which again is pretty cool. This is how you do that:

This is the generated schema:

It looks OK to me! See how it correctly created the relationships!

You can check the whole thing at Github. Be sure to alter your connectionstring in App.Config.
Maybe you see something that is completely wrong or against good practice. I’d be happy to hear it!

Next time I’ll cover Nhibernate, ASP.NET MVC 3 and Dependency Injection.