WCF – NHibernate Unit Of Work Endpoint Behavior
OK, my last WCF-related code snippet of the day, I promise. This is quite similar to the last one. I required that the WCF service I was developing started a new NHibernate Session for each invocation, and closed it after invocation (i.e. session-per-request). I couldn’t rely on the ASP.NET session start and end events in global.asax as this particular WCF service was to respond to MSMQ messages rather than HTTP.
So, once again I found myself bashing out a custom EndpointBehavior to add a custom CallContextInitializer to every operation:
using System;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
/// <summary>
/// Being a custom EndpointBehavior added to the WCF services such that each operation begins a
/// new unit of work when invoked, and closes the same unit of work after invocation.
/// </summary>
/// <remarks>
/// In practice, we are using this simply to manage NHibernate sessions - opening a new Session at
/// the start of each operation, and closing it as the operation completes.
/// </remarks>
public class UnitOfWorkEndpointBehavior : IEndpointBehavior
{
/// <summary>
/// Local instance of unit of work implementation.
/// </summary>
/// <remarks>
/// Interface is ORM-agnostic, it need not be NHibernate.
/// </remarks>
private IUnitOfWork unitOfWork;
/// <summary>
/// Initializes a new instance of the UnitOfWorkEndpointBehavior class.
/// </summary>
/// <param name="unitOfWork">Unit of Work</param>
public UnitOfWorkEndpointBehavior(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
// Add a new Unit of Work call context initializer to every operation.
foreach (DispatchOperation operation in endpointDispatcher.DispatchRuntime.Operations)
{
operation.CallContextInitializers.Add(new UnitOfWorkCallContextInitializer(this.unitOfWork));
}
}
public void Validate(ServiceEndpoint endpoint)
{
}
}
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
/// <summary>
/// Custom call context initializer added to all WCF operations such that each operation begins
/// a new unit of work when invoked, and closes the same unit of work after invocation.
/// </summary>
/// <remarks>
/// In practice, we are using this simply to manage NHibernate sessions - opening a new Session at
/// the start of each operation, and closing it as the operation completes.
/// </remarks>
public class UnitOfWorkCallContextInitializer : ICallContextInitializer
{
/// <summary>
/// Local instance of unit of work implementation.
/// </summary>
/// <remarks>
/// Interface is ORM-agnostic, it need not be NHibernate.
/// </remarks>
private IUnitOfWork unitOfWork;
/// <summary>
/// Initializes a new instance of the UnitOfWorkCallContextInitializer class.
/// </summary>
/// <param name="unitOfWork">Unit of Work</param>
public UnitOfWorkCallContextInitializer(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
/// <summary>
/// Method fired after the operation is invoked.
/// </summary>
/// <param name="correlationState"></param>
public void AfterInvoke(object correlationState)
{
// End the unit of work (closes the NH session).
this.unitOfWork.End();
}
/// <summary>
/// Method fired before the operation is invoked.
/// </summary>
/// <param name="instanceContext"></param>
/// <param name="channel"></param>
/// <param name="message"></param>
/// <returns></returns>
public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
{
// Begin a new unit of work (opens the NH session).
return this.unitOfWork.Start();
}
}
And the Windsor configuration is much the same as before:
container.Register(
Component.For<UnitOfWorkEndpointBehavior>()
.Attribute("scope").Eq(WcfExtensionScope.Services));









Nice .. Cherers for that Ian , I’m just chewing over a similar structure .. Who knows ,I may even post my take .