The Entity Framework DbContext (or LINQ-to-SQL DataContext) is a Unit Of Work implementation. That means that the same DbContext should be used for all operations (both reading and writing) within a single web or service request. That means that there are a lot of different places where the DbContext have to be accessed. To avoid having to pass the DbContext around as a parameter, I’ve created a UnitOfWorkScope that makes the DbContext ambient and easily accessible.
A common beginners problem when working with Entity Framework or LINQ-to-SQL is to have too short life times of the DbContext. A problem that I’ve seen many questions about on Stack Overflow is when questions are encapsulated in repositories or helper methods. Inside each method a new DbContext is created for that specific read. Later, when the returned entity has been updated and is to be saved the problem occurs. The entity should be saved using the same DbContext that once read it from the database to allow change tracking to work properly. Clearly, having separate DbContexts is a problem.
The first attempt to solve it is usually to pass the DbContext around. That only solves half the problem though, that of accessing it. The other half of the problem is to decide where to call SaveChanges to persist the changes done. Calling it from every method making changes spoils the entire unit of work concept. Trusting the creator of the context to know when any of a myriad of called functions have made changes seems risky.
I’ve been looking for a better way to handle the DbContext and have come up with an ambient DbContext, using a UnitOfWorkScope which is similar to TransactionScope.
The main features of the UnitOfWorkScope are:
The first method in the call chain opening a UnitOfWorkScope creates an ambient DbContext.
Subsequent methods in the call chain utilizes the same DbContext.
Changes are only saved if all participating scopes called SaveChanges
Read only mode is available, where data is read using the existing DbContext, but no changes need to be saved. This is useful for GetSomeThing methods that are used both for pure reading and for reading for update.
When writing code I think that it is important to keep in mind what type of code it is. Far too often, I see people writing very complicated structures without the need. I think that a reason for this is that the code was inspired from some library. Unless reading other people’s code for fun, library code and interfaces is what an average developer is most likely to get in touch with, so it is natural to be inspired by it. Unfortunately it can lead very wrong.
Library code is very special; it is meant to be reusable in different applications, under different circumstances. It has to be extendable and adaptable without code changes.
Writing code whose behaviour can change without code changes is of course challenging and requires wide spread usage of dependency injection.
Application code is just used in one environment and can be changed to alter the behaviour. As an example of the difference, I’ll implement a sample logging mechanism. One written as application code and one written as library code.