Entity framework and the asp.net action filter based unit of work

Hackered
Monday, February 2, 2015
by Sean McAlinden

Over the last few years I've been living in the cloud...

Well not literally, I've been mainly working on really large apps with very different storage requirements than the previously typical relational database approach.

Part of a recent project has been creating a simple editor application sitting on top of a SQL server database.

The application was very Microsoft orientated involving Asp.Net MVC and Asp.Net Web API so it made sense to use the Entity framework 6.

Whilst I have used it before a few years back, I've always been more on the NHibernate side of the fence so kind of excited and kind nervous due to bad EF memories.

First thing I noted was it is actually pretty good now, a lot of the annoying aspects are gone and it pretty much worked out of the box as expected.

I managed to wrap a nice repository pattern over the top with ease and all the lambda based parameters made life very easy, so far so good.

Then came the unit of work...

An entity framework context is essentially a unit of work, however thinking back to the good old days of OpenSessionInView and similar, I wanted to be able to use the same context across multiple repositories and save it all at the end of the web request.

Utilising the same context throughout was relatively straight forward, I am using Castle Windsor so registerd the DBContext with a PerWebRequest lifestyle and injected it into my repositories.


I also had to add the following to the web.config:

<system.webserver> 
  <modules> 
    <add name="PerRequestLifestyle" type="Castle.MicroKernel.Lifestyle.PerWebRequestLifestyleModule, Castle.Windsor"></add> 
 </modules>
</system.webserver>

Now the context is nicely shared between all of my repositories, I just needed a nice way to call save at the end of the web request.

First thing that caught me out was the application_endrequest method in the global asax... note: this runs after the end of the PerWebRequest lifestyle.

After trying out a few other approaches which all seemed to have slight issues, I have settled on using an ASP.Net MVC action filter attribute similar to the following:

public class UnitOfWorkFilterAttribute : ActionFilterAttribute
{
    public override void OnResultExecuted(ResultExecutedContext filterContext)
    {
        var context = (MyContext)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IMyContext));

        if (context == null || !context.ChangeTracker.HasChanges())
        {
            return;
        }

        context.SaveChanges();
    }
}

I registered this globally in my ASP.Net MVC filter config:

filters.Add(new UnitOfWorkFilterAttribute());

And that's it, for a very small amount of code I have a nice and simple per request level unit of work pattern with ASP.Net MVC and the Entity Framework, my venture back into the Entity Framework is going well so far...