Try fast search NHibernate

12 October 2009

NHibernate & WCF : session-per-call in uNhAddIns

We have added a new project in uNhAddIns to work with NHibernate and WCF.

As you know the most common, and probably the most recommended, way to manage the NH’s session in WCF is session-per-call. The session-per-call pattern has the same behavior of session-per-request where, in this case, call, NH’s session and NH’s transaction has the same life cycle.

There are various ways to add this behavior to your WCF-service, the one I have used in uNhAddIns is through ICallContextInitializer. In addition there is a trivial IInstanceProvider to instantiate your services through a service-locator (in this case through Common Service Locator).

NhSessionPerCallContextBehavior

As usual, in uNhAddIns, what I’m using, as “Context”, is the implementation of ICurrentSessionContext. To work with session-per-call you must configure NHibernate with the ThreadLocalSessionContext (yes! the same we are using for tests, winForm and WPF applications).

        <property name="current_session_context_class">
uNhAddIns.SessionEasier.Contexts.ThreadLocalSessionContext, uNhAddIns
</property>

XML configuration

The XML configuration is the one I prefer because it is the less intrusive (you don’t need any reference to uNhAddIns.WCF).

Your contract may look as:

[ServiceContract]
public interface IMagazineService

and its implementation may look as

public class MagazineService : IMagazineService
{
private readonly IDaoFactory daoFactory;

public MagazineService(IDaoFactory daoFactory)
{
this.daoFactory = daoFactory;
}

The service configuration should look:

<behaviors>
<
serviceBehaviors>
<
behavior name="YourApp.Services.MagazineServiceBehavior">
<
serviceMetadata httpGetEnabled="true"/>
<
serviceDebug includeExceptionDetailInFaults="false"/>
<
InstanciateThroughServiceLocator/>
<
nhibernateBehavior/>
</
behavior>
</
serviceBehaviors>
</
behaviors>
<
extensions>
<
behaviorExtensions>
<
add name="nhibernateBehavior"
type="uNhAddIns.WCF.NhSessionPerCallBehaviorExtensionElement, uNhAddIns.WCF, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
<
add name="InstanciateThroughServiceLocator"
type="uNhAddIns.WCF.ServiceLocatorBehaviorExtensionElement, uNhAddIns.WCF, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</
behaviorExtensions>
</
extensions>

I’m using the WCF’s behaviorExtensions to inject both behaviors: the service instantiation through the service locator and the NH’s session-per-call.

Attributes configuration

If you don’t like the XML configuration, and you can deal with a strong reference to an “external” assembly, you can use the attribute-way. Doing so your implementation should look as:

[InstanciateThroughServiceLocator]
[NhSessionPerCall]
public class MagazineService : IMagazineService
{
private readonly IDaoFactory daoFactory;

The service locator configuration

To configure the IoC container I’m using the service factory and my dear guy-wire.

public class MyServiceHostFactory : ServiceHostFactory
{
IGuyWire guyWire;
public RoadtripServiceHostFactory()
{
guyWire = ApplicationConfiguration.GetGuyWire();
guyWire.Wire();
}
}

and the Markup of the service

<%@ ServiceHost Language="C#"
Debug="true"
Factory="YourApp.Services.MyServiceHostFactory"
Service="YourApp.Services.MagazineService"
CodeBehind="MagazineService.svc.cs" %>

That’s all… a piece of cake!!

3 comments:

  1. there's samething that works with .net remoting?

    thanks

    ReplyDelete
  2. Is the Session cache is used here ?
    if every call you get a new session, isn't it inefficient ?

    ReplyDelete
  3. No it isn't (as in session-per-request).

    ReplyDelete