Ayende @ Rahien

Unnatural acts on source code

Using NHibernate Session Per Request with WCF Windsor Integration

Okay, this is a quickie, but here is how you can do it, you need to register a UnitOfWorkEndPointBehavior implementation on the container, and make sure that your WCF services are used through the WindsorServiceHost. That is all. What is the UnitOfWorkEndPointBehavior, you ask, here it is:

public class UnitOfworkEndPointBehavior : IEndpointBehavior
{
	public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
	{
		foreach (DispatchOperation operation in endpointDispatcher.DispatchRuntime.Operations)
		{
			operation.CallContextInitializers.Add(new UnitOfWorkCallContextInitializer());
		}
	}
}

public class UnitOfWorkCallContextInitializer : ICallContextInitializer
{
	public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
	{
		ISession session = factory.OpenSession();
		OperationContext.Items["NHibernate_Session"] = session;
		return session;
	}

	public void AfterInvoke(object correlationState)
	{
		((IDisposable)correlationState).Dispose();
	}
}

public static class UnitOfWork
{
	public static ISession Current { get { return (ISession )OperationContext.Items["NHibernate_Session"]; }
}

Comments

Andrew
06/14/2007 11:50 AM by
Andrew

Awesome stuff! Thanks Ayende - I have been wanting to do something like this for months.

Diego
06/15/2007 01:06 AM by
Diego

Hi,

Could you please create a simple example with physical layer separation?? Thanks!

Ayende Rahien
06/15/2007 10:47 AM by
Ayende Rahien

Physical layer separation? You mean two different processes?

Diego
06/15/2007 12:36 PM by
Diego

No, I mean running the IIS and the SqlServer in different machines. So WCF has sense.

Thanks again!

Ayende Rahien
06/15/2007 12:41 PM by
Ayende Rahien

I still don't get the problem, you just need to change the connection string, no?

Diego
06/15/2007 12:52 PM by
Diego

Yes, but what if I want to separate the business logic from the UI.?

or what is this example for?

Ayende Rahien
06/15/2007 12:56 PM by
Ayende Rahien

Let us take it two steps back.

This is a post about infrastructure. If you want to use NHibernate from your WCF service (or call to a controller that uses NH), this shows you how this can be done easily. I am not following the BL vs. UI discussion, I am afraid.

Phil Degenhardt
06/25/2007 07:52 AM by
Phil Degenhardt

Thanks Ayende. This doesn't seem to work if the operation is returning an object with a lazy collection. The session is disposed before WCF serializes it and you get a "Failed to lazily initialize a collection - no session" error. Any ideas?

Ayende Rahien
06/25/2007 08:08 AM by
Ayende Rahien

Load it eagerly?

I am sure that the scope of the opened session can be expanded, but I am not to where it should

Phil Degenhardt
06/29/2007 01:27 AM by
Phil Degenhardt

Thanks. Just for the record I was able to overcome this by creating an IExtension and disposing the session after the OperationCompleted event.

Jeff Fansler
07/18/2007 02:34 AM by
Jeff Fansler

Excuse me for what probably should be obvious, but I don't see an Items collection off of the System.ServiceModel.OperationContext object. What am I missing?

http://msdn2.microsoft.com/en-us/library/system.servicemodel.operationcontext_members.aspx

Ayende Rahien
07/18/2007 05:48 AM by
Ayende Rahien

I just checked, it doesn't exists, very strange. I assumed that something of this nature would exists

Jeff Fansler
07/18/2007 02:10 PM by
Jeff Fansler

I'm glad I'm not nuts. Do you have any suggestions on how to store the session for the given OperationContext? Everything about this concept makes sense and works for me, I just don't have a good idea for where to store the session.

Thanks,

Jeff

Ayende Rahien
07/18/2007 03:57 PM by
Ayende Rahien

not of the top of my head , I don't know WCF enough to tell.

Lance Cranford
07/20/2007 04:22 AM by
Lance Cranford

I'm working on a current design (following this model) for storing Sessions in WCF. Try storing the session in Extensions property of the OperationContext. This would be a class that extended IExtensible. You can then retrieve this specific extension instance by using OperationContext.Current.Extensions.Find(). I'm still working on the design but let me know what you find

Comments have been closed on this topic.