One DbContext per request in ASP.NET MVC (without IOC container)

devuxer picture devuxer · Jun 13, 2011 · Viewed 25k times · Source

Apologies if this has already been answered, but how do you guarantee one Entity Framework DbContext per request if you are not using an IOC container? (The answers I've come across so far deal with IOC container solutions.)

It seems like most solutions hook into the HttpContext.Current.Items dictionary, but how do you guarantee disposal of the DbContext when the request is finished? (Or is disposal not absolutely necessary with an EF DbContext?)

Edit

I'm currently instantiating and disposing my DbContext in my controllers, but I also have several separate instantiations of my DbContext in ActionFilters and my MembershipProvider (and I just noticed, also a couple validators). So, I thought it might be a good idea to centralize instantiation and storage of my DbContext to reduce overhead.

Answer

walther picture walther · Apr 14, 2012

I know this is not a recent question, but I'll post my answer anyway, because I believe someone may find it useful.

As probably many others, I followed the steps mentioned in the accepted answer. Yay, it works. HOWEVER, there's one catch:

Methods BeginRequest() and EndRequest() fire each time a request is made, but not only for aspx pages, but for ALL STATIC CONTENT! That said, if you use the code mentioned above and you have on your page let's say 30 images, you're re-instantiating your dbcontext 30 times!

The solution for this is to use a wrapping class for retrieving the context, something like this:

internal static class ContextPerRequest
{
      internal static DB1Entities Current
      {
          get
          {
              if (!HttpContext.Current.Items.Contains("myContext"))
              {
                  HttpContext.Current.Items.Add("myContext", new DB1Entities());
              }
              return HttpContext.Current.Items["myContext"] as DB1Entities;
          }
      }
 }

And then for disposing

protected void Application_EndRequest(object sender, EventArgs e)
{
   var entityContext = HttpContext.Current.Items["myContext"] as DB1Entities;
   if (entityContext != null) 
      entityContext.Dispose();
}

This modification ensures that you instantiate and dispose your context only once per request and only when needed. Selected answer instantiates context every single time.

Note: DB1Entities is derived from DbContext (generated by VS). You would probably want to alter it with your context name ;)

Note 2: in this example I'm working with just one dbcontext. If you need to work with multiple, you would need to modify this code according to your needs. Don't take this as some ultimate solution to world problems, because it certainly isn't a final product. It is meant just to give a hint, how it may be achieved in a very easy way.

Note 3: Same approach can be used in different situations as well, for instance when you'd like to share an instance of SqlConnection or any other... This solution isn't exclusive to DbContext object, nor to Entity framework.