Dave Paquette

Caffeine Driven Development

Managing Entity Framework DbContext Lifetime in ASP.NET MVC

March 27, 2013

Managing the lifetime of a DbContext instance in your application is extremely important. A DbContext makes use of important resources like database connections that need to be released. If you do not properly dispose of a DbContext instance, the underlying database connections might never be released back to the connection pool. Anyone who has done any old school ADO.NET programming knows the madness that lies down that path.

In an ASP.NET MVC application, the DbContext instances are typically used inside a controller. For some background, controllers in MVC are created when as a web request comes in and they are disposed of when that request is completed. In ASP.NET MVC controllers, how can we ensure that our DbContext instance is disposed? (Spoiler Alert: You should use option 3)

Option 1) The Using Pattern

One option is to use the using pattern:

using (EmployeeContext context = new EmployeeContext())
{
    return View(context.Employees.ToList());
}
using (EmployeeContext context = new EmployeeContext())
{
    return View(context.Employees.ToList());
}

The using pattern ensures that the EmployeeContext is disposed of at the end of the using block. It is basically shorthand for a try{… } finally{…} block where the context is disposed of in the finally. This pattern will ensure that the context is disposed, but it makes it difficult to share a context instance in different points of the application. You may find yourself creating more DbContext instances than you intended. It also adds some noise to your controller logic. While it is much cleaner than a try finally, it does still add noise.

Option 2) The Dispose Pattern

Another option is to implement the dispose pattern in your controller:

public class EmployeeController : Controller
{
    private EmployeeContext _context;
 
    public EmployeeController()
    {
        _context = new EmployeeContext();
    }
        
    public ActionResult Index()
    {
        return View(_context.Employees.ToList());
    }
        
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _context.Dispose();
        }
        base.Dispose(disposing);
    }
}
public class EmployeeController : Controller
{
    private EmployeeContext _context;

    public EmployeeController()
    {
        _context = new EmployeeContext();
    }
        
    public ActionResult Index()
    {
        return View(_context.Employees.ToList());
    }
        
    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _context.Dispose();
        }
        base.Dispose(disposing);
    }
}

Again, this pattern ensures that the EmployeeCotenxt is disposed of when the controller is disposed of at the end of the request. Much like the using pattern, this option adds noise to your controller and it makes it difficult to share an instance of a context with different points in your application. It also relies on all developers on the team to properly implement the dispose pattern (one of the most misused patterns in the .NET world).

Option 3) Dependency Injection

This is the option that I choose. It is the cleanest possible option and it relieves the controller any responsibility for the lifetime of the DbContext instance. When you think about it, the controller requires an instance of a DbContext, but it really shouldn’t care about where it comes from or where it goes when it is done with it.

Start by adding a constructor that requires an instance of the DbContext.

public class EmployeeController : Controller
{
    private EmployeeContext _context;
 
    public EmployeeController(EmployeeContext context)
    {
        _context = context;
    }
        
    public ActionResult Index()
    {
        return View(context.Employees.ToList());
    }
}
public class EmployeeController : Controller
{
    private EmployeeContext _context;

    public EmployeeController(EmployeeContext context)
    {
        _context = context;
    }
        
    public ActionResult Index()
    {
        return View(context.Employees.ToList());
    }
}

Since this is the only constructor, we know that the EmployeeController cannot be created without an instance of an EmployeeContext. It is no longer the responsibility of the controller to create the DbContext, which means it is no longer responsible for disposing of it either. Notice how simple the controller is now?

But wait! If the controller isn’t creating the context, then who is? This is an MVC application, who is creating the controllers? How can I be sure that the context is actually being disposed?

IoC Container to the Rescue!

Luckily,there are a number of dependency injection / IoC containers that have hooks in to MVC to help us with this. My favorites is NInject, but I have also had good luck with Autofac and others.

To get started with NInject, simply install the NInject.MVC3 nuget package.

Install-Package Ninject.MVC3

The nuget package will add a NInjectWebCommon.cs file to your application’s App_Start folder:

image

 

The important line in this file is the line that registers the OnePerRequestHttpModule:

DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));

You also need to add the following line to the CreateKernel method in NInjectWebCommon.cs

kernel.Bind<EmployeeContext>().ToSelf().InRequestScope();
kernel.Bind<EmployeeContext>().ToSelf().InRequestScope();

With this configuration, NInject will recognize that your controller requires an instance of an EmployeeContext and do the following for you:

-Create an instance of the EmployeeContext

-Pass the instance in to the EmployeeController constructor

-Dispose of the EmployeeContext at the end of the Http Request

Because we are using OnePerRequestHttpModule, the default behaviour is to create a new instance of the EmployeeContext for each Http request.  That means different requests will never share an instance of a context. It will also ensure that no more than one EmployeeContext is created, even if the request ends up hitting 3 controllers that all require an EmployeeContext. In other words, the lifetime of the context is tied to the life of the request.  This is a good thing and is definitely the recommended approach for Entity Framework.  Use it!

 

Update 1: Updated to add the very important NInject configuration that ensures instances of the EmployeeContext are actually disposed properly. Thank you to my friend Robson (@TowTweets) for pointing this out!

13 thoughts on “Managing Entity Framework DbContext Lifetime in ASP.NET MVC

  1. Fred says:

    Wow! Thanks for the article. I have been reading several “tutorials” on injection and IoC. I have to say that your example was the simplest explaination I have found. Those others that described your option 3 threw so much other stuff in there that it was nearly impossible to make sense of.

    Thanks again.

  2. Miloskov says:

    Awesome post, it is what I was looking. DbContext and Ninject that works great.

    Also I want to get rid of the repository pattern because Dbcontext already have all that abstraction.

  3. Concrete Gannet says:

    Options 2 and 3 assume that every action method will need the DbContext. If not, it should be created on demand in the methods that need it. In other words, back to option 1. I worry that one day someone will add a new action method that doesn’t need a DbContext, and won’t realize they should change from option 3 to option 1.

    • admin says:

      I would not be overly concerned about an action method that does not require the DbContext. The overhead of creating a DbContext instance is very low. The underlying database connection is not created until the context is actually used (ie. when you access any of the DbSet properties).

  4. Pingback: DbContext Lifecycle In WCF Service Hosted In IIS | Technology & Programming Answers

  5. John says:

    When I implement your option 3 I get an error that says “no default constructor “. If I add default constructor, I get an error when using my context instance because it is created by default constructor. What to do? Thank you for great post

    • Hi John,

      What class is causing the error? What parameters does your constructor take? I suspect that with your default constructor you will need to call your other constructor and pass a default value for each parameter.

      Dave

  6. Lance says:

    Hi Dave,

    I used your post about six months ago, and all worked wonders. I now need my dbContext class to be initiated with a constructor, but try as I may, I just can’t get it to work. This is where I ended up, but it still calls the default constructor. Any thoughts?

    kernel.Bind().ToSelf().InRequestScope().WithConstructorArgument(“connectionString”, “conString-here”);

    • Are you missing the DbContext generic argument? The statement below should work, replacing with your particular DBContext:

      kernel.Bind().ToSelf().InRequestScope().WithConstructorArgument(“connectionString”, “conString-here”);

  7. sahar says:

    Thanks for this great article.. I hope you add option 4 to implement interface using repository pattern instead of the dbcontext itself . thanks again.

  8. Pingback: Gerenciando o tempo de vida do Entity Framework DBContext | Eriko Morais

  9. Erik says:

    Hi there,

    this is an interesting article. Nice work!
    You mentioned the “NInject.MVC3″ nuGet package, however i am currently targetting MVC 5 and i did not find a “Ninject.MVC5″ on Nuget.

    I can probably just install the latetst version of Ninject, but then i don’t know how to make ASP.NET MVC provide an instance of the Dbcontext to all my controllers.

    What do you recommend for a IOC beginner like me?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code lang=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" extra="">

Current day month ye@r *