good explanation of nh facility session management

15 views
Skip to first unread message

Shawn Hinsey

unread,
Nov 3, 2009, 1:43:26 AM11/3/09
to castle-pro...@googlegroups.com
I'm having a bit of trouble understanding exactly how session
management works when using the NH facility in an ASP.NET MVC
environment, particularly when it comes to lazy loading. I'm not sure
if the pattern in the documentation of disposing the session inside of
a dao/repository method is the best way to go or if there is another
approach I should be using.

Can anyone point me at a good resource? I haven't had much luck
googling. I took a look at S#arp Architecture but I wasn't really sure
where to start, so a pointer to a source file in their repo would also
be appreciated.

Thanks,
Shawn

Tuna Toksoz

unread,
Nov 3, 2009, 2:10:57 AM11/3/09
to castle-pro...@googlegroups.com
in a web environment, what is done in NH Facility is that the session is opened at the beginning of the http request, stored in web session. Atthe end of the request, it is committer and disposed. Using this logic allows you to have lazy loading working pretty easily. It comes with downsides, though. 

Tuna Toksöz
Eternal sunshine of the open source mind.

http://devlicio.us/blogs/tuna_toksoz
http://tunatoksoz.com
http://twitter.com/tehlike

Jason Meckley

unread,
Nov 3, 2009, 8:44:40 AM11/3/09
to Castle Project Users
I use session per request with all my web apps. NH also has built-in
support for managing the session using an ICurrentSessionContext
implementation. some information on the topic can be found here
http://www.nhforge.org/doc/nh/en/index.html. search for
"ICurrentSessionContext" (section 2.3.)

using an IoC container and HTTP module.

1. begin request: resolve factory, open session and bind to current
context. (manage transaction here as well)
2. inject ISession as a dependency on my controllers and services. IoC
containers usually have way to override how/where an object is
resolved. with castle i use either a factory method to
ISessionFactory.GetCurrentSessionContext(); or a SubDependencyResolver
if I'm using more than 1 session factory.
3. end request: resolve factory, unbind session from context. dispose.



On Nov 3, 2:10 am, Tuna Toksoz <tehl...@gmail.com> wrote:
> in a web environment, what is done in NH Facility is that the session is
> opened at the beginning of the http request, stored in web session. Atthe
> end of the request, it is committer and disposed. Using this logic allows
> you to have lazy loading working pretty easily. It comes with downsides,
> though.
>
> Tuna Toksöz
> Eternal sunshine of the open source mind.
>
> http://devlicio.us/blogs/tuna_toksozhttp://tunatoksoz.comhttp://twitter.com/tehlike

Shawn Hinsey

unread,
Nov 3, 2009, 11:58:52 AM11/3/09
to castle-pro...@googlegroups.com
So to clarify, even though I might dispose a session from the session
manager, it will be kept alive until the end of the request by the
infrastructure?

I would have to set it up again but I am fairly certain I saw behavior
roughly like this:

MyPersistentObject po;

using(var session = _sessionManager.OpenSession()
{
po = session.Find...
}

// later, in a controller

po.LazyCollection

throw an exception about a missing session.

Jason Meckley

unread,
Nov 3, 2009, 1:21:57 PM11/3/09
to Castle Project Users
no, you are still managing the session's scope. you simply tie the
scope of the session to the request.

you would *not* have using blocks in your code
using(var s = f.opensession())
{
}

here is the code I'm using the manage session scope and transactions.

public class SessionModule : IHttpModule
{
private TransactionScope transaction;

public void Init(HttpApplication context)
{
context.BeginRequest += OpenSessions;
context.EndRequest += DisposeOfSessions;
}

private void OpenSessions(object sender, EventArgs e)
{
var options = new TransactionOptions {IsolationLevel =
IsolationLevel.ReadCommitted};
transaction = new TransactionScope
(TransactionScopeOption.Required, options);

var session = WindsorContainerAccessorUtil
.ObtainContainer()
.Resolve<ISessionFactory>()
.OpenSession();
ManagedWebSessionContext.Bind(HttpContext.Current,
session);
}

private void DisposeOfSessions(object sender, EventArgs e)
{
if (HttpContext.Current.Error == null)
transaction.Complete();

var factory = WindsorContainerAccessorUtil
.ObtainContainer()
.Resolve<ISessionFactory>();
ManagedWebSessionContext.Unbind(HttpContext.Current,
factory).Dispose();

transaction.Dispose();
}

public void Dispose()
{
}
}

then I have my controllers and/or services
public class MyController : SmartDispatchController
{
private ISession session;

public MyController(ISession session)
{
this.session = session;
}
}

and finally the facility to wire all this together
public class NhibernateFacility : AbstractFacility
{
protected override void Init()
{
var configuration = Fluently
.Configure()
.Database(MsSqlConfiguration
.MsSql2000
.ProxyFactoryFactory(typeof
(ProxyFactoryFactory).AssemblyQualifiedName)
.ConnectionString(builder =>
builder.FromConnectionStringWithKey("key")))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<Entity>
())
.ExposeConfiguration(cfg => cfg
.SetProperty
(Environment.PrepareSql, true.ToString())
.SetProperty
(Environment.CurrentSessionContextClass, typeof
(ManagedWebSessionContext).AssemblyQualifiedName))
.BuildConfiguration();
var factory = configuration.BuildSessionFactory();

Kernel.AddComponentInstance<Configuration>(configuration);
Kernel.AddComponentInstance<ISessionFactory>(factory);
Kernel.Register(Component
.For<ISession>()
.LifeStyle.Is(LifestyleType.Transient)
.UsingFactoryMethod(k =>
k.Resolve<ISessionFactory>().GetCurrentSession()));
}
}

this approach also requires the FactoryFacility to use the factory
methods. You could replace the factory method with a
SubDependencyResolver.

On Nov 3, 11:58 am, Shawn Hinsey <smhin...@gmail.com> wrote:
> So to clarify, even though I might dispose a session from the session
> manager, it will be kept alive until the end of the request by the
> infrastructure?
>
> I would have to set it up again but I am fairly certain I saw behavior
> roughly like this:
>
> MyPersistentObject po;
>
> using(var session = _sessionManager.OpenSession()
> {
>    po = session.Find...
>
> }
>
> // later, in a controller
>
> po.LazyCollection
>
> throw an exception about a missing session.
>
> On Tue, Nov 3, 2009 at 2:10 AM, Tuna Toksoz <tehl...@gmail.com> wrote:
> > in a web environment, what is done in NH Facility is that the session is
> > opened at the beginning of the http request, stored in web session. Atthe
> > end of the request, it is committer and disposed. Using this logic allows
> > you to have lazy loading working pretty easily. It comes with downsides,
> > though.
>
> > Tuna Toksöz
> > Eternal sunshine of the open source mind.
>
> >http://devlicio.us/blogs/tuna_toksoz
> >http://tunatoksoz.com
> >http://twitter.com/tehlike
>

Shawn Hinsey

unread,
Nov 3, 2009, 5:39:25 PM11/3/09
to castle-pro...@googlegroups.com
This is using your own custom NH facility, right? It's my
understanding that the castle NH facility does these things for you,
it's just not entirely clear to me how to use it. I don't see why else
using it in web mode would require the use of an HttpModule, but I
can't simply take a dependency in ISession unless I am missing some
step not covered in the documentation.

I will build this out along the lines you've discussed if I need to,
but I'd prefer not to own that code if I can avoid it.

Jason Meckley

unread,
Nov 3, 2009, 7:41:51 PM11/3/09
to Castle Project Users
the mechanics of NH Manager are more complex then they need to be.
that may be the state of NH when it was first introduced.I also don't
like the dependency on required castle xml configs, when I can write
it out in code using FNH. It's really straight forward setting up
session per request. another reason I like rolling my own: managing
the dependencies across projects is much simpler. FNH is the only 3rd
party extension on top of NH.

On Nov 3, 5:39 pm, Shawn Hinsey <smhin...@gmail.com> wrote:
> This is using your own custom NH facility, right? It's my
> understanding that the castle NH facility does these things for you,
> it's just not entirely clear to me how to use it. I don't see why else
> using it in web mode would require the use of an HttpModule, but I
> can't simply take a dependency in ISession unless I am missing some
> step not covered in the documentation.
>
> I will build this out along the lines you've discussed if I need to,
> but I'd prefer not to own that code if I can avoid it.
>

Shawn Hinsey

unread,
Nov 3, 2009, 7:53:44 PM11/3/09
to castle-pro...@googlegroups.com
The only non-web.config standard XML config I have in my MVC app is
log4net. I have the factory, nhibernate, logging, and ATM facilities
and am resolving controllers from Windsor 2.0.

I will end up implementing session per request if I have to, but I
want to make sure I understand how to use the castle stuff before i
write my own because the castle code will always have more eyes on it
than mine.

Shawn Hinsey

unread,
Nov 7, 2009, 5:23:03 PM11/7/09
to castle-pro...@googlegroups.com
Incidentally, I figured out what my problem was. If you're using
Windows 7 or IIS 7 on 2k8, you need to register the module in
system.webserver.modules, not system.web.httpmodules (or maybe in
addition to, I have both so it runs on IIS6).
Reply all
Reply to author
Forward
0 new messages