Your own NHibernate SessionFactory for Web applications

The beauty of the Castle Windsor container is that it allows you the flexibility to do many things with a relatively small API without having to learn all the many pluggable components out there. In short, sometimes you don’t need to use contribs just because they are available, doing so increases your coupling and in turn reduces your flexibility – abstraction comes at a price. Case in point the NHibernate Facility, this allows you to create a session instance for each web request, the key benefit being that you can use lazy loading on your entities and take full advantage of the unit of work which NHibernate does so well. The point is you don’t need this facility, and I’ll show you how to create the same behaviour without it.

These are the components you need to create:

1. Windsor Container implementation: a wrapper plus configuration.

This will be used for all your dependency injection needs, including supplying NHibernate sessions to services at runtime.  You will notice that I have named the NhibernateSessionOpener - “nhsessionopener”, you can find the component referring to this in the configuration file.

public class Container
{
private static IWindsorContainer _container;
public static IWindsorContainer Instance
{
get
{
if (_container == null)
{
_container = new WindsorContainer(configuration);
_container.Register(Component.For<NhSessionOpener>()
.Named("nhsessionopener"));
}
return _container;
}
}
}

Container Configuration:


<?xml version="1.0" encoding="utf-8" ?>
<configuration>

<facilities>
<facility id="factory.support"
type="Castle.Facilities.FactorySupport.FactorySupportFacility,
Castle.MicroKernel"
/>
</facilities>

<components>
<component id="nhsessionimpl" lifestyle="PerWebRequest"
type="NHibernate.Impl.SessionImpl, NHibernate"
factoryId="nhsessionopener"
factoryCreate="Open" />

<!-- Other components follow here -->
</components>

</configuration>

2. NHibernate SessionFactory wrapper

You only need one NHibernate SessionFactory which will be accessible from this wrapper instance. 


public class NhibernateSessionFactory
{
private static ISessionFactory instance;

public static ISessionFactory Instance
{
get
{
if (instance == null) instance = create();
return instance;
}
}

private static ISessionFactory create()
{
var cfg = new NHibernate.Cfg.Configuration();
cfg.AddAssembly(Assembly.GetAssembly(typeof(MyAssembly)));
return cfg.BuildSessionFactory();
}
}

3. A regular Factory class to return Nhibernate sessions.

public class NhibernateSessionOpener
{
public static ISession Open()
{
return NhibernateSessionFactory.Instance.OpenSession();
}
}

The delegation pipeline

This diagram demonstrates how it all fits together:

pipeline



Programmatic usage:

var session = Container.Instance.Resolve<SessionImpl>();


Configuration for constructor or setter injection:

<component id="myComponent" type="MyAssembly.MyNamespace.MyComponent, 
MyAssembly.MyNamespace"
>
<parameters>
<Session>${nhsessionopener}</Session>
</parameters>
</component>


So to wrap up, whilst you do need to do a little work setting this up this is really only the addition of two small classes, the benefit of course is that you have more flexibility and are not hampered by unnecessary abstraction.


Comments

No comments posted yet.

Post Comment

Title *
Name *
Email
Url
Comment *  


Please add 8 and 4 and type the answer here: