Do you use StructureMap? NHibernate? Good. Have you tried using them with WCF? Yeah, me too. It didn’t go so well for me either. StructureMap, NHibernate, and WCF all worked fine. They did nothing wrong. I guess it was my journey to find out how to make them work together that felt painful. So how did I do it? I Googled it, of course. This led me to read a few varying accounts of how others made it work. Each scenario was different than mine in some significant way (of course) so they each gave me a piece of the whole picture.
First, I tackled with getting StructureMap working with WCF. This wasn’t nearly as problematic as it could have been. Thanks to Jimmy Bogard for writing up a walkthrough on how to make it work.
Jimmy’s post: http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/07/29/integrating-structuremap-with-wcf.aspx
Second, I had to get NHibernate opening sessions per request, which is different than a typical request in an ASP.NET application. This is where the trouble started. I followed a second post by Jimmy discussing this very issue.
Jimmy’s Other Post: http://www.lostechies.com/blogs/jimmy_bogard/archive/2008/09/16/integrating-structuremap-and-nhibernate-with-wcf.aspx
So this got me further but eventually I began having weird issues. As in things working and then not working out of nowhere. Eventually after some frustration I began to suspect a threading issue. Sure enough, In a discussion on the StructureMap User Group, Jimmy mentioned that the solution may have threading problems. Awesome.
So, Googling I found another post by Frank-Leonardo Quednau who described a different approach.
Frank-Leanardo’s Post: http://realfiction.net/?q=node/167
Using the OperationContext.Current.InstanceContext.Extensions collection to store the NHibernateSession because the instance context only lives once for the service request. The idea being that you can open the Session when the InstanceProvider starts and close the Session when it release the service instance.
I followed the post and nearly got it working pretty well, but my project structure didn’t work very well with how it was setup. I don’t know if it’s because of my UnitOfWork or FluentNHibernate or what, but things just didn’t line up for me.
So here is what I ended up doing. (Sorry for the images. It looked better than our style for inline code. Don’t worry though all the code will be posted at the end. And Here.)
1. In my WCF application I created my StructureMap Registry. The registry wires up all my object instances at runtime. You’ll notice that the ServiceinstanceContextBuildPolicy; this is a custom build policy (caching policy is a better term maybe) which instructs StructureMap to cache it’s objects in a special way for WCF (per service instance). More on that later. Everything else here is pretty run of the mill. I create an NHibernate Session from my SessionSource (fluentNHibernate) which sets up my UnitOfwork and creates an instance of my Repository to do the Querying, Loading, Saving of my domain objects.
2. To setup this registry, I needed a BootStrapper. The BooStrapper is initializing StructureMap with my registries, in this case I only have one, but I could add more later.
3. To get call the BootStrapper I needed a StructureMapServiceHostFactory.
4. The StructureMapServiceHostFactory creates instances of…StructureMapServiceHosts. The StructureMap Service Host isn’t necesarily the best name for it. The Service Host is responsible to add the InstanceCreationService Bahavior, when a Service Host is opened.
5. The InstanceCreationServiceBehavior wires up two things. First it wires up the InstanceProvider which does the “heavy lifting” for our UnitOfWork. Things like Initialize, Commit, RollBack, and Dispose.
Notice that after the finally block, I check for the InstanceContext.Extensions to Remove the InstanceCreationExtension. Doing so fires the Detach Event which calls the DisposesAndClear() method on our StructureMap Cache living inside of the InstanceCreationExtension. So where is that InstanceCreationExtension added? Well, in our InstanceCreationInitializer of course! :)
5.a. The InstanceCreationBehavior also wires up an InstanceCreationInitializer which enables the Custom Cache Policy from above, to work. The Initialize method adds a new InstanceCreationExtension which is being created with a null StructureMap InstanceCache as you see below.
6. So the InstanceCreationExtension is quite important to this whole thing working properly. Its job is to create and destroy the StructureMap InstanceCache when it is added and removed from the service instance.
7. Whew! so now that we have all that in place we still need StructureMap to use that Extensions collection to store the InstanceCache. The InstanceCache in structureMap is where it stores all of it’s Instantiated Objects. So in this case (refer to the Registry) the UnitOfWork and NHibernateUnitOfWork are being stored there but I want a new one every time a new Service Instance is started.
RED: This is where I check for an existing InstanceCreationExtension which stores our StructureMap InstanceCache. I learned the hard way that many of these things can be null so you’ll see I do a lot of checking for null instances of many things here. YELLOW: This is where the InstanceCache which will be returned to StructureMap is being set. GREEN: This is where I’m adding that InstanceCache back to our InstanceCreationExtension so that when StructureMap calls this Cache Policy again it will find it.
RED: This is where I check for an existing InstanceCreationExtension which stores our StructureMap InstanceCache. I learned the hard way that many of these things can be null so you’ll see I do a lot of checking for null instances of many things here.
YELLOW: This is where the InstanceCache which will be returned to StructureMap is being set.
GREEN: This is where I’m adding that InstanceCache back to our InstanceCreationExtension so that when StructureMap calls this Cache Policy again it will find it.
Eventually I have a Cache to return to StructureMap so it can grab the object that was being requested. For us, the requested instanceCache will have our NHibernateUnitOfwork on it.
So…Given a ServiceContract that looks like this:
I can do things like this:
My Repository will be injected by StructureMap and will have the UnitOfWork on it to execute the query against the database. The next time this Service is called a new UnitOfWork will be created and we’ll start the whole thing all over again.
If you’ve read this much I appreciate the time you’ve taken sitting through this lengthy post. So as a reward, please feel free to download the code and play around with it. I know it’s not perfect and I’m very open to the possibility that there is a better way to do this. If you have any suggestions please let me know. I appreciate any feedback. As long as it’s good feedback. :)
DOWNLOAD: GET THE CODE HERE!
Related posts
Comments
February 17. 2009 17:32
ooooh I was so close to getting there My only thought is in the ServiceInstanceProvider: public object GetInstance(InstanceContext instanceContext, Message message) { 1: _unitOfWork = ObjectFactory.GetInstance<IUnitOfWork>(); 2: _u nitOfWork.Initialize(); 3: return ObjectFactory.With(_unitOfWork).GetInstance(_serviceType); } between lines 1 and 3 as this provider is a singleton but is called for each new instance, could you not end up creating a new unit of work then then another instance request would enter and that unitofwork variable is ovewritten by a subsequent new. That same unitof work is now assigned to two instances. M@t
MattC
February 17. 2009 17:52
That's a good point about it being a singleton. I haven't seen that happen, but I think that's because it doesn't need to be a member of the instance provider. I'm really only using it as a temporary variable of the instantiated object. I think I might get away with using a local variable to that method. But maybe not. I'll change my code and see if the test still passes.
Ryan Montgomery
February 17. 2009 18:47
I found that if I fired lots a simultaneous requests at a service and removed the check for null before calling dispose on the release instance that I got a null reference exception. Now, obviously removing the null check isn't staying but it did highlight that maybe that unitofwork instance had been disposed in a different service instance that was sharing the same object.
M@t
April 7. 2009 18:08
Hi there,I downloaded the code and I found it quite interesting and workable. With your permission I may incorporate a few of the concepts in my current project, where incidentally I am also using StructureMap.Cheers
Frank Quednau
April 22. 2009 12:37
Nice post! I have gone down the same path as you (starting with Jimmy Bogards post). A quick question: Dont you have to make sure that your service is served be a new instance everytime using: [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)] Otherwise there is a risk that your unitofwork is reused by different service requests!? /Andreas
Andreas Öhlund
July 1. 2009 16:53
nice blog.
vajinismus
Home
© Rapidparts, Inc 2008 | 2950 Walkent Ct. NW, Grand Rapids, MI 49544 | Phone 616.647.2500 | info@rpionline.com