From the last days of playing around with and learning NHibernate it's quite clear to me that NHibernate is not a perfect match for a WCF solution. I'm perfectly aware of the fact that I'm still a total NH newbie, so please correct me or help me out if you can.
From the moment I heard of Hibernate years ago I thought it was best made for stateful solutions and not web apps or web services, and from what I can see that is still the case. I like many of the things I see in NH, especially the way you can map existing and bad looking databases to better looking domain entities, and the work on NHibernate Fluent looks promising.
You have to understand how lazy loading does (not) work with web services and serializing problems you may run into. But I think the biggest problem lies in the session management of NHibernate and where to open and close your NHibernate session. I won't even go into the different options proposed by hundreds of bloggers, just Google it. The thing is I don't want to be dependant on more 3rd party or open source components than necessary - it can easily get out of control.
I still want to use NHibernate for our WCF project because I do think can help us map the old, existing database we have to work with to decent domain entities, but I'm afraid we will run into weird problems later on. This approach seems to be one of the best so far, but I need to test it out some more and I'm not sure it will handle lazy loaded/HasMany data. Quite a few projects have run into problems with the session being closed before the serialization of lazy loaded objects happens :/
We may have to use EF instead.
This blog post is to continue on the one I wrote a few days ago about a new architecture for a WCF project we're trying out.
My colleague Tomas and I sat down the whole day yesterday and dug into the topic and came out with a first rough code architecture that seems to work. Both of us knows WCF pretty well, but we're new to Unity and NHibernate so this baby has to be tested thoroughly :)
First, thanks to Ray Henry, who wrote a couple of nice posts about how to use Unity with WCF. That information was superb. Basically we're using a custom Service Host Factory which we point at from the .svc markup file:
<%@ ServiceHost Language="C#" Debug="true" Service="WcfUnity.TestService"
CodeBehind="TestService.svc.cs" Factory="WcfUnity.UnityService.UnityServiceHostFactory" %>
The UnityServiceHostFactory is where we currently registers the types that is to be injected into our code. Right now we're doing it in code, and we're only working with 2 classes; the NHibernate Repository and the NHibernate Session Manager (which is a singleton):
protected override ServiceHost CreateServiceHost(Type serviceType, Uri baseAddresses)
var unity = new UnityContainer()
.RegisterType<INHibernateSessionManager, NHibernateSessionManager>(new ContainerControlledLifetimeManager());
var host = new UnityServiceHost(serviceType, baseAddresses)
Container = unity
The Session Manager is responsible for setting up the NHibernate Session Factory which is expensive and you only want to do that once. In short - the factory creates a new WCF service host which creates a service behavior which is called each time before a requested service class is instantiated. To be able to resolve and inject our registered classes, the behavior uses a specific instance provider which does Resolve as part of its GetInstance() method. It's all described in detail by Ray in his post, so go check it out. I've not seen a better example of Unity + WCF out there yet and from what I can see in our, so far limited, testing it works well.
When that plumbing is done (some 4 small classes, that's all), we got a very clean service implementation class with the IRepository injected into it:
public class TestService : ITestService
private readonly IRepository _repository;
public TestService(IRepository repository)
_repository = repository;
// ITestService members goes here...
You don't see any trace if a container, just the way it should be. Currently we're looking at our Repository interface and a decent syntax for a Unit Of Work. I'm fond of the lambda style of coding, and I'm playing something like this now:
var response = new GetPersonResponse();
var person = _repository.Find<Person>(request.Id);
ret.Person = person;
Or for a transaction:
var response = new AddPersonResponse();
response.Person = _repository.Find<Person>(request.Person.Id);
The TransactionalUnitOfWork method would do things like:
public void TransactionalUnitOfWork(Action action)
_session = sessionManager.GetSession();
var transaction = _session.BeginTransaction();
The "problem" is that the UoW shouldn't go into the repository implementation, it's wrong but I'm only trying things out here. I might as well wrap the opening and closing of a NH Session and transaction within an IDisposable and call it my UoW as many others have done before me, but I kind of like this. Have to think about not letting things that should stay inside the repository "leak" out... At this moment we're only playing around with things :)
We also need to encapsulate and inject business rules in a good way as we will host the services at more than one customer with different rules. MEF could be an option actually... more on that later :)
We're thinking about a new architecture for a set of pretty large WCF (and perhaps also REST) services that's going to be developed during the next year and perhaps you dear reader would like to comment!
The services themselves are pretty straight forward, we're going to serve data from a huge SQL Server database which unfortunately is old and lacks relationship/fk/pk between most tables. Nothing we can do about that I'm afraid but we thought that nHibernate could be a good way to map data to domain objects. Some of the services will need to handle more complex business rules, but no heavy computing or long running stuff (not atm anyway).
What more can I say... everything is going to be running on .NET 3.5, and we have a pretty good view of the business domain, we're currently modelling the information/domain together with the customer and we will probably be developing the whole thing in a DDD-ish way, using unit and integration tests, IoC...
So, currently we're thinking of WCF/REST for the service layer, Unity as container and building something around nHibernate for the Repository (looking at the IRepository implementation in Fluent). We're new to nHibernate but have been looking at nHibernate.Linq which looks really nice, and I think we'll use the Fluent API and map the classes in code instead of using XML configuration (which I'm allergic against). Just have to figure out a good way to make it all fit together, especially to get a decent UnitOfWork to work with the nHibernate session and the repository. I'll see what I come up with and post it here.
Ideas? Please comment or send me an email of you like.