Solving LINQ's N-Tier Issues
Ok, so maybe solving is somewhat of a misnomer, but we certainly can combat them with strength and conviction. A little background on the subject first; LINQ has proven to be somewhat of a booger when attempting to work with it in a streamlined development environment when incorporating any sort of N-Tier pattern.
Why you ask should it be a problem...the common answer I've heard many many times is, why should it be any different? You have at the essence of it some pretty simple logical and physical layer guidelines right? It's well known in the industry at this point to create N-Layer app's to solve things like SOC (separation of concerns) and physical or network boundaries.
But what about LINQ....how does it change anything we've done before? Here's the tricky part: LINQ objects, created outside a context are considered unattached - which works great...but the moment you have to refer to an object in relation to it's context you run into major issues. That object is then tied to that context and believe it or not; there's no easy or reliable way to detach it.
Not such a big deal right...statefull objects are a good thing! Not really...
Imagine the very common scenario below:
- You use LINQ to query for a customer reference
- You add an order to the reference of that customer
- You try to put the customer back with the order now attached...
BOOM....head-shot - unless you've got the original context that you queried for the customer under...there is no way to get that customer back into the database. Keep in mind that a DataContext is not serializeable, so if your response is to pass the datacontext around, you'd be right as soon as you enter an SOA pattern.
Now, before you go off the deep end, I realize that this problem is CAUSED by the Utilization of LINQ itself. Because we are passing objects around - we run into the very real situation that the object is carrying a reference to it's context. Rick Strahl has done quite a few posts as of late on this same topic.
The typical solution, and usually one of the first answers on forums, blogs, and otherwise is...pass messages, not objects. Ok, I can concede to that. In true N-Layer applications we can very well send messages. This achieves the whole "loosely coupled" layers, and enables easily things like a provider model, a stateless BLL, an application aware server...etc. My response usually is: I don't need all that...what I need to be able to do is pass the objects back and forth. LINQ was nice enough to generate them for me, so why should I recreate each and every one of my objects (about 300 of them), in a serialized or class object format - just to overcome LINQ being a pain in the ass.
If you read Rick's blog, you'll see a very complete example of creating a set of business objects wrapping the LINQ functionality, where he abstracts out things like the context creation, the submit changes, and attachment of objects. That's pretty cool stuff...but yet even a little to big for my project.
Without you as the reader knowing specifically the scope of my project - it's hard to get behind this article...so let me help you out a little:
- Our physical boundary is the SQL state machine, which we can overcome with SQL Protocols
- We are working in a thick client, 1 to 3 user environment without a lot of need for initial scalability
- Our application state will be managed individually by the client. They don't need to be sentient to other running app's.
- We will maintain database concurrence through a first write wins methodology.
Ok, so now that you have the basic layout - you can see that we aren't truly trying to build an N-Layer application. Our use for N-Layer would have been to separate concerns between business logic, and data access. These would be logical layers with little or no need to exist outside the maintainability in our programming model.
Ok, so on to what I'll call the X-Layer pattern. ;) It's always nice to invent something new huh. Maybe it will catch fire. Keep in mind, that the representation of this is only as a "prototype" pattern. I don't have security, object state, or validation included. Those things snap easily into the datacontext though through the extension of the LINQ partial classes.
I could describe the project all day long, but it's just as easy to look at it. So I'll include it for your review: