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.

12 Replies to “Nhibernate, ASP.NET MVC 3 and Ninject”

  • I commented on your earlier Fluent NHibernate post about DI. Thanks for this post however I’m still confused about the decoupling as your PersonRepository is bound to NHibernate so you couldnt swap in DB4O easily.

    Maybe I’m missing something?

    • Hi Jon, thanks for your comments!
      I probably had to name my PersonRepository NHPersonRepository. Then it would make more sense. I will see if I can plug Db4o in the example later today, as a proof of concept for Dependency Injection. 😉

    • Well, I actually replaced Nhibernate with Db4o quite easily. I renamed PersonRepository to NHPersonRepository and created a Db4oPersonRepository added the Db4oSession stuff.
      I had to plumb the Global.asax though.. and I had some discrepancies between the NHibernate Session and the Db4O Session. But I did not have to touch the Controllers and the Views. So that is a good thing.

  • I’ve been reading a bit more about DI and NHibernate and I have seen a comment that NHhibernate uses Castle.Windsor as its default IOC. Fancy doing a post about wiring up a MVC 3 app, NHibernate and Castle.Windsor?

    • Hm, I already thought of that but take a look at the documentation on their site! It’s ancient! But I could give it a shot, for the sake of it..
      Or you could try and we could share code 🙂

  • I know its more mature than others but I thought as it uses it by default and I also might look at using Castle ActiveRecord it would be a good combination. I might not use ActiveRecord and therefore look at Ninject or Munq or other IOC but for now I thought I’d try the above. Will let you know how I get on. Also documentation is not that great I find or too bloated for just simple examples.

  • Excellent thanks.

    I spent the last few days trying to build NHibernate, Byte.Castle, Fluent NHibernate and Windsor in a solution but it wasn’t working out. Somewhere along the line there was a version mismatch dependency.

    In the end I created a solution added a package reference via NuGet and got it all compiled. I then tried to update all references to the latest thinking it was bound to break but it worked.

    This has been a learning curve which is good as I enjoy learning although not sure how keen I am to swap out Windsor if I decide to use another IOC. Not exaclty easy stuff this!

    On a seperate design issue I was wondering if I could get your thoughts. If I am injecting interfaces into
    controller constructors to resolve a ProductsRepository class to
    IProductsRepository in a ProductsController, if later on I then need to make
    a check for something in one of the Actions against orders I would then have
    to create a new instance of the class eg/OrderRepo orderRepo = new
    OrderRepo. At that point I am now bound to that class rather than the
    interface. In this case would you recommend inserting a IOrdersRepository
    into the controller constructor, resolve the class with Windsor and then it
    can be used in the Action I need? This is probably not a great example as the model should have a relationship but say if you had a IWebSiteSettings repository and you needed it in one action, would you still pass it into the constructor?

  • Hi, Just curious… what if I wanted to store all my nhibernate Mappins, Config etc. within my repository layer alongside my database configuration, create my modules within my domainservice layer then DI inject from my ASP.NET MVC app, how would I configure my ISession? I do not want to let my web app know about NHibernate… my entities are in a seperate project which is accessed by the web app, repo layer and domain service?

Laat een reactie achter op Jon Reactie annuleren

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *

%d bloggers liken dit: