Blog of Keith Craig, containing my thoughts, comments and questions. RSS Feed


LINQ and n-tier architecture: choices, choices, choices...

One question when architecting an n-tier application using LINQ to SQL or LINQ to Entities is how far to commit to using LINQ. In other words, how deeply should you let the database LINQ technologies permeate the layers of the application. I've seen two general approaches:

  1. Commit fully to LINQ, and have the entire application use the objects that are being tracked for changes by the DataContext or ObjectContext. If you're using stateful model objects with stateless layers, this conceptually looks something like this:

    N-tier application with LINQ objects used in all layers

  2. Commit partially to LINQ, and have the business and presentation layers of the application use non-tracked objects. Confine LINQ to SQL or LINQ to Entities to the data access layer (DAL) only. This means you have two sets of objects: one for the data access layer, and another set for the other layers:

    N-tier application using LINQ objects in the data access layer, and another set of objects in the other layers

There are several reasons to commit fully (option 1 above):

  • You get a lot in return: objects are automatically tracked by the context for changes, and then all changes can be saved with only a single method call.
  • The context automatically ensures that you don't accidentally load two instances of the same object. (If you do, it quietly hands you another reference to the original object in memory.)
  • This is also less code than option 2, as you only have one set of stateful objects, and you don't need to write code to go back and forth between the LINQ and non-LINQ objects.

Some reasons to not commit fully to LINQ (option 2 above) include:

  • It makes it much easier to remove LINQ later--it's confined to the DAL, and there are no LINQ dependencies in the business or presentation layers.
  • Committing fully to LINQ (option 1) makes the n-tier architecture a bit less clean--for example, any lazy loading that happens in the business logic can be considered data access logic that has escaped from the DAL. By confining LINQ objects to the data access layer (option 2), there won't be any LINQ objects to cause lazy loading in the business layer or presentation layer.
  • If you are using LINQ to SQL, then it allows the business and presentation layers to use objects that are not identical in structure to the database tables. (This is more of a reason to use LINQ to Entities than to not commit fully to LINQ.)
  • Due to the way LINQ to SQL is designed, it can be difficult to use in an n-tier architecture. For example, it's not currently possible to set the DataLoadOptions after the DataContext has been used to return data. One possibility is to forgo using DataLoadOptions entirely, but it depends on the application if that's a viable option. Another option is to organize the DataLoadOptions by page, and set the DataLoadOptions specific to a given page in the OnInit event handler of the page. However, these are a bit strange.

Choices, choices--what to do? Here are my thoughts/guidelines:

  • If the application is fairly complex, tend toward option #1 (commit fully to LINQ to SQL/LINQ to Entities). By complex, I mean that you have object graphs with collections and/or many objects. In this case, the object change tracking from LINQ is great when you are adding, removing, and altering objects, and saves a huge amount of effort--enough to make it easily worth committing to LINQ fully.
  • On the other hand, if you generally are working with a single object or a very few objects at a time in the code, object change tracking is much less valuable--you know which objects you've changed in this type of code. In this case, option #2 becomes less unattractive.
  • Generally, tend toward LINQ to Entities (and the Entity Framework) rather than LINQ to SQL. There are many benefits to LINQ to Entities over LINQ to SQL, including the fact that it fits into an n-tier architecture more easily.

Personally, I like option #1--you get a lot of benefit from going "all in" with LINQ. And I enthusiastically suggest using LINQ to Entities rather than LINQ to SQL--you get a lot more flexibility.

Note that, if you are converting an existing application to use LINQ, it might make sense to restrict the LINQ objects to the data access layer if it simplifies the conversion. (This will of course vary depending on the existing application's architecture.)

 
Posted by Keith Craig | 2 Comments | Trackback Url | Bookmark with:        
Tags:

Links to this Post

Comments

Thursday, 6 Mar 2008 02:05 by A compromise?
I've been working on decoupling LINQ backed classes from the database implementation. It's been tricky, but I've made some pretty good progress. I'm blogging my results it here: http://sogeti-phoenix.com/Blogs/author/swilliams.aspx

Tuesday, 12 May 2009 01:40 by Kalyan
Well explained. The basic LINQ Architecture can be found here http://www.techbubbles.com/net-framework/linq-architecture/

Name:
URL:
Email:
Comments:

CAPTCHA Image Validation