Linq To Sql Web App Lifetime Management - Take 1

I was asked to help another project team at work to come up with a good way to manage Linq To Sql data contexts on their project.  Their current situation is that they open and use a datacontext wherever needed, but often run into problems where they're trying to save entities with expired contexts or opening too many connections to the database to grab the same record multiple times.  They're not fully utilizing the datacontext's features such as the Identity Map or Unit Of Work.

I haven't had much experience with Linq prior to being asked to help, but I knew the basics.  For the rest, I decided to do a bunch of blog reading on the subject to help out with my implementation.  My criteria for a good solution was the following:

Ease Of Use / Clean Syntax
I figured this one was self-explanatory.  First, I didn't want to get into a huge architecture if I didn't have to and furthermore, I figured that if it wasn't easy to implement and use, no one would want to do the work to implement it.

Unit Testable:
I like to do unit testing and wanted to be able to write tests that didn't actually hit the database.  I wanted to be able to write mock versions of the implementation instead for tests so I could control them during my tests.

Unit Of Work/Lifetime Management:
This was to solve the problem that they came to with me in the first place.  Microsoft, as well as common sense, indicate that you should really only have one datacontext around per request for web applications.  This seems to make sense since the datacontext already is built like a unit of work (it records all changes to entities, inserts and deletes and waits until SubmitChanges() to actually persist them to the database).

Validation Of Entities:
Another concern the team had was how to validate entities before saving them.  Their current implementation was to create partial classes for each entity and create custom attributes to perform validation.  I did not include my solution as part of the prototype I came up, but I actually suggested they pull the validation out into separate Specification objects - this way, they can keep the entity classes to solely what Microsoft provides them and the Specification objects can be reused, as well as making more explicit the business rules around a valid entity - something I learned from reading Eric Evans' DDD book.

What I came up with was pretty simple. I mostly just took a lot of what other bloggers were suggesting and stripped out a lot of stuff I didn't think was necessary at the moment.  Not that I felt others were over-complicating the matter, but they were showing examples of things they needed for their projects which may not necessarily be needed in this one.  And taking the YAGNI approach, I felt like I should keep it as simple as possible, knowing that I could add in the desired features later if necessary.

So, finally, here is the design I came up with...

   1:  public class UnitOfWork : IUnitOfWork
   2:  {
   3:       private readonly EntityClassesDataContext context;
   4:   
   5:       public UnitOfWork()
   6:       {
   7:            context = new EntityClassesDataContext();
   8:       }
   9:   
  10:       public Table<T> GetTable<T>() where T : class
  11:       {
  12:            return context.GetTable<T>();
  13:       }
  14:   
  15:       public void SubmitChanges()
  16:       {
  17:            context.SubmitChanges();
  18:       }
  19:  }

This UnitOfWork class just wraps the DataContext and implements an IUnitOfWork interface which can then be used in the rest of the system, so that we can mock it during tests.  It just provides the ability to get a table (which can then be queried, or inserted to/deleted from) and run SubmitChanges().  I considered having SubmitChanges() be run automatically at the end of each request, but I felt like that was dangerous as you may not want all changes submitted - I want to make it more explicit and require programmers to call that function when they wanted their changes persisted.

   1:  public class UnitOfWorkFactory
   2:  {
   3:       private const string HTTP_CONTEXT_KEY = "SFT.UnitOfWork.Factory.Context.Key";
   4:   
   5:       public static IUnitOfWork GetUnitOfWork()
   6:       {
   7:            if (HttpContext.Current != null)
   8:            {
   9:                 if (!HttpContext.Current.Items.Contains(HTTP_CONTEXT_KEY))
  10:                 {
  11:                      HttpContext.Current.Items.Add(HTTP_CONTEXT_KEY, Activator.CreateInstance(typeof(UnitOfWork)));
  12:                 }
  13:                 return (IUnitOfWork)HttpContext.Current.Items[HTTP_CONTEXT_KEY];
  14:            }
  15:            throw new Exception("No current HttpContext found.");
  16:       }
  17:  }

This factory is used to get the current UnitOfWork which is stored in HttpContext's Items collection.  It's pretty simple.  If you ask for the current UnitOfWork and it hasn't been created for the current request yet, it creates it and puts into the Items collection.  Then, it returns it.  Otherwise, if it already exists, it returns the one that's in the Item's collection already.  From what I read, this should guarantee that you always use the single, per-request DataContext which means you take advantage of the Identity Map (instead of loading the same entity from the db multiple times) and have all your changes in a request tracked.

   1:  public DefaultPresenter(IDefaultView view) : this(view, UnitOfWorkFactory.GetUnitOfWork(), new DebtorRepository())
   2:  {
   3:  }
   4:   
   5:  public DefaultPresenter(IDefaultView view, IUnitOfWork unitOfWork, IDebtorRepository repository)
   6:  {
   7:       this.view = view;
   8:       this.unitOfWork = unitOfWork;
   9:       this.repository = repository;
  10:  }

And this is how I used the factory in my prototype.  Dependency injection allows for unit testing because in the unit tests, I can use the 2nd constructor and pass in a mock of the IUnitOfWork, but in production, I can use the above constructor which calls on the UnitOfWork factory to get the concrete UnitOfWork class that wraps the Linq datacontext.

I know that IoC containers would get me down to one constructor, but for the purposes of the prototype, I didn't want to do the extra work.  However, itt's probably something I would suggest if this is used in an actual project.

The last thing which I won't post is that I use Repositories for getting data.  I do that cut down on the duplication of queries across the codebase and also to abstract out the Table classes that come with the datacontext since they're not easily mocked for testing.  I read about ways that you could mock them out and provide data from an in-memory data store during testing, but when I'm testing the presenters, I don't want to have to worry about all the overhead of setting that up in my test, so I'd rather just put it behind an IRepository interface.  When it comes time to test the Repository classes, I can focus on how to write the tables with an in-memory data collection.

And that's it.  I would love some feedback as this is my first time taking up something like this.  Is there any obvious, or not-so-obvious flaw in this design that I'm missing?  Are there any ways it could be improved?  Your comments would be greatly appreciated.