Nhibernate, WCF and SessionContext

443 views
Skip to first unread message

Andyk

unread,
Nov 12, 2009, 12:36:51 PM11/12/09
to nhusers

Hi,
can anyone tell me which sessioncontext should be used in a Wcf
environment.
Currently I have a web application calling a WCF service, hosted in
IIS. The WCF service does all the work and uses NHibernate.

I am using sessioncontext in a static class to manage nhibernate
session like this:

public static ISession GetCurrentSession()
{
if (!CurrentSessionContext.HasBind(SessionFactory))
{
CurrentSessionContext.Bind(SessionFactory.OpenSession
());
}
return SessionFactory.GetCurrentSession();
}

and in the config I have:
<property name="current_session_context_class">call</property>

When multiple users access the system, exceptions start being thrown,
such as "Session is closed". Which gives me the impression the session
is being shared, and isnt unique to each request.

Currently, for each WCF function, Im calling:
NhibernateHelper.BeginTransaction();
// Do work
NHibernateHelper.CommitTransaction();
NHibernateHelper.DisposeSession();

There's something Im doing wrong, but Im racking my brains trying to
find the solution.

Any response gratefully appreciated.


Andy

Jason Meckley

unread,
Nov 12, 2009, 1:30:11 PM11/12/09
to nhusers
my first guess is that you never unbind the session from the context.
i would that there. if that doesn't work I would then browser the
ICurrentSessionContext implementations to see which is best suited for
your scenario.

finally, there is also the issue of managing the scope of the session.
I have worked with NH in 3 contexts.
Web
Service Bus
ThreadPool.QueueWorkItem()

with the web i open a transaction and session when a request begins
and commit/rollback and dispose of the session when the request ends.
combined with the post-redirect-get model for processing command
quests I haven't had an issue yet.
with a service bus it's similar. open a transaction and session when a
message is received and commit/rollback and dispose of the session
when processing the message has completed.
thread pool is a little trickier to explain. the code may be more
useful
ThreadPool.QueueWorkItem(item => {
using(var session = factory.OpenSession())
using(var tx = session.BeginTransaction())
{
CurrentSessionContext.Bind(session);
item();
tx.Commit();
CurrentSessionContext.Unbind(factory);
}
});

Andyk

unread,
Nov 12, 2009, 3:16:43 PM11/12/09
to nhusers
Yes, Im pretty much doing the same thing, begin...commit/
rollback...dispose.

If I run my WCF service with ASP.Net compatibility turned on, and use
"web" as my SessionContext, would that be a better scenario?
Or should I be sticking with "call"?

Fabio Maulo

unread,
Nov 12, 2009, 3:42:47 PM11/12/09
to nhu...@googlegroups.com

Donald Belcham

unread,
Nov 12, 2009, 4:21:37 PM11/12/09
to nhu...@googlegroups.com

There’s also this that I’ve written up and made the code available for.  Links to code and samples are in the blog post.  Have used this on a number of projects and had no issues with it to this point.

 

http://igloocoder.com/archive/2009/05/01/a-little-more-wcf-nhibernate.aspx

 

Donald




--
Fabio Maulo

No virus found in this incoming message.
Checked by AVG - www.avg.com
Version: 8.5.425 / Virus Database: 270.14.61/2498 - Release Date: 11/12/09 07:38:00

Andrew Rimmer

unread,
Nov 12, 2009, 2:36:08 PM11/12/09
to nhu...@googlegroups.com
From what I have read, the simplest way of using WCF with NHibernate is to configure the Session and wrapping transaction to fit around one WCF call. This emulates how many people use NHibernate in a web environment, were a session is opened in begin_request and closed in end_request.

Andrew

Sandra

unread,
Nov 13, 2009, 8:02:53 AM11/13/09
to nhusers
Hi Fabio

Thanks for the article but I cannot make it work.
I've changed my config file as mensioned in your article.
Here is how my service looks like:

private IWindsorContainer container;

public MyService(IWindsorContainer container)
{
this.container = container;
}

I get the following error message on NhSessionPerCallContextBehavior's
constructor: 'Object reference not set to an instance of an object.'
This is because ServiceLocator throws an exception.

appreciate your help.

Sandra

Fabio Maulo

unread,
Nov 13, 2009, 6:27:20 PM11/13/09
to nhu...@googlegroups.com
I'm using that implementation in WindowsAzure and it is working fine.
In your service you shouldn't inject the container but the DAO/Repository or DaoDactory and blahblah
The other matter is the service factory.
As service factory I'm using a service-locator and, as described in the post, I'm using

in this case with the implementation for Castle.Windsor.

wait... perhaps there is an example in uNhAddIns (I can't recall everything...).. no.. I'm moking the SL in the test..
btw
var sl = new WindsorServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => sl);
container.Register(Component.For<IServiceLocator>().Instance(sl));

2009/11/13 Sandra <sandra...@gmail.com>



--
Fabio Maulo

Fabio Maulo

unread,
Nov 13, 2009, 6:28:56 PM11/13/09
to nhu...@googlegroups.com
ah...
and don't forget to configure NH
        <property name="current_session_context_class">
uNhAddIns.SessionEasier.Contexts.ThreadLocalSessionContext, uNhAddIns
</property>

2009/11/13 Fabio Maulo <fabio...@gmail.com>



--
Fabio Maulo

Andyk

unread,
Nov 16, 2009, 7:46:16 AM11/16/09
to nhusers
Thanks Fabio and Donald. It was quite an insight realising that Wcf
doesnt (by default) generate a context per call.
Explains alot of our problems.

Thanks for the help.


Andy

On 13 Nov, 23:28, Fabio Maulo <fabioma...@gmail.com> wrote:
> ah...
> and don't forget to configure NH
>
>         <property name="current_session_context_class">
>            uNhAddIns.SessionEasier.Contexts.ThreadLocalSessionContext, uNhAddIns
>        </property>
>
> 2009/11/13 Fabio Maulo <fabioma...@gmail.com>
>
>
>
>
>
> > I'm using that implementation in WindowsAzure and it is working fine.
> > In your service you shouldn't inject the container but the DAO/Repository
> > or DaoDactory and blahblah
> > The other matter is the service factory.
> > As service factory I'm using a service-locator and, as described in the
> > post, I'm using
> >http://www.codeplex.com/CommonServiceLocator
>
> > in this case with the implementation for Castle.Windsor.
>
> > wait... perhaps there is an example in uNhAddIns (I can't recall
> > everything...).. no.. I'm moking the SL in the test..
> > btw
> > var sl = new WindsorServiceLocator(container);
> > ServiceLocator.SetLocatorProvider(() => sl);
> > container.Register(Component.For<IServiceLocator>().Instance(sl));
>
> > 2009/11/13 Sandra <sandraekr...@gmail.com>
Reply all
Reply to author
Forward
0 new messages