views:

138

answers:

3

I have just started learning NHibernate.

Over the past few months I have been using IoC / DI (structuremap) and the repository pattern and it has made my applications much more loosely coupled and easier to test.

When switching my persistence layer to NHibernate I decided to stick with my repositories. Currently I am creating a new session on each method call but of course this means that I can not benefit from lazy loading.

Therefore I wish to implement session-per-request but in doing so this will make my web project dependent on NHibernate (perhaps this is not such a bad thing?). I was planning to inject ISession into my repositories and create and dispose sessions on beginrequest/endrequest events (see http://ayende.com/Blog/archive/2009/08/05/do-you-need-a-framework.aspx)

Is this a good approach? Presumably I cannot use session-per-request without having a reference to NHibernate in my web project?

Having the web project dependent on NHibernate prompts my next (few) questions - why even bother with the repository? Since my web app is calling services that talk to the repositories, why not ditch the repositories and just add my NHibernate persistance code inside the services? And finally, is there really any need to split out into so many projects. Is a web project and an infrastructure project sufficient?

I realise that I have veered off a bit from my original question but it seems that everyone seems to have their own opinion on these topics. Some people use the repository pattern with NHibernate, some don't. Some people stick their mapping files with the related classes, others have a separate project for this.

Many thanks, Ben

A: 

I wouldn't make the business logic dependent on NHibernate. I wrote a (more or less simple) class to create the session into a context:

using (TransactionService.CreateTransaction())
{
  // use repository here

  // rollback on exception, only commit when reach this last line:
  TransactionService.Commit();
}

You just get an IDisposable, you don't need to know the session.

The repositories gets an API to access the session. For instance:

// example repository implementation
public Entity Get(Guid id)
{
  return SessionProvider.Session.Get<Entity>(id);
}

To implement this, I put the session into a ThreadStatic variable, which is initialized in CreateTransaction and returned by SessionProvider.Session.

Stefan Steinegger
@Stefan, can you explain how this works with session per request. How/where are you creating and disposing of the session?
Ben
I create the session in `TransactionService.CreateTransaction`. there I return a tiny class which implements `IDisposable` and calls the `TransactionService` in Dispose (I actually send an event which is registered by the `TransactionService` when it creates this object.) There the session is closed. When your request comes in, you open the transaction by using `TransactionService.CreateTransaction`. Then it is there.
Stefan Steinegger
@Stefan - care to share the code for your TransactionService? No offence, but the above code doesn't really help me as it stands.
Ben
It consists of some classes and is coupled with our infrastructure. So even if I could, it wouldn't help you much. The key is the ThreadStatic variable which represents the context. The rest is actually just an API built around it.
Stefan Steinegger
A: 

You may want to look at the TransactionScope class:

http://msdn.microsoft.com/en-us/library/system.transactions.transactionscope.aspx

Burt
+1  A: 

Take a look at S#arp Architecture. It answers everything you need, including, how to separate data layer (NHibernate), web layer, and business logic.

queen3