Common causes of DbContext has been disposed
On several occasions over the last couple of years I’ve seen the following exception being thrown in web applications that use Entity Framework.
Once you know what might cause this issue it becomes quite obvious and easy to fix but for a junior developer or someone who hasn’t experienced it before it can be quite tedious to diagnose hence writing this post in the hope that it may help someone in the future.
Generally I’ve noticed two problems that cause this error.
IOC Container Lifestyle
The first is incorrect configuration of lifestyle/lifetime of dependencies.
Take for example an MVC web application that uses a framework such as SimpleInjector or Ninject.
In most cases your dependencies (including your DbContext) will use Request Scope
so that for each request in the web application a new instance of your dependencies will be generated and through the life time of that request the same instance of your dependencies will be used. However if you were to use a different life style you may find yourself experiencing issues.
Often when this is the cause of the issue you may not start seeing the exceptions until your code is already in production and even then it can be intermittent. For example if you were to use a transient
lifestyle for your DbContext
a new instance is created every time a context is injected, the IOC container generally doesn’t keep a track of transient lifestyle objects and therefore doesn’t dispose of them however garbage collection will get rid of these objects at some point. This is why it may appear intermittent as you don’t know when garage collection will occur.
Ensuring you fully understand the different lifestyles of the ioc container of your choice and using them appropriately will help prevent this exception.
Async Calls
The other common cause I’ve seen of this exception is when using asynchronous calls to objects that depend on DbContext
.
If you forget to await
and asynchronous call the code will continue to run with out waiting for the asynchronous call to be completed therefore the following may happen.
- A new request is created within the web application
- When required the IOC container generates an instance of
DbContext
- An asynchronous call is made that uses the
DbContext
- The code continues to run and the request may complete before the asynchronous code has completed.
- The IOC container sees the request end and disposes of the objects it instantiated (including the
DbContext
). - The asynchronous code tries to use the
DbContext
which is now disposed. - A
System.InvalidOperationException: The operation cannot be completed because the DbContext has been disposed.
exception is thrown.
When this is the cause of the issue it can be more difficult the find the exact code that is the culprit however generally Visual Studio should offer guidance when asynchronous code is called without using await
or another language construct that would cause the code to wait whilst the asynchronous code is completed. It’s worth checking the Error List in Visual Studio for any warning in relation to this.
Again this can sometimes present itself intermittently and depend upon how long the asynchronous code takes to execute and how long the code following the asynchronous call takes to execute. It becomes a race condition which completes first.
There are other scenarios where this exception may occur but these are two common causes that I’ve seen on several occasions.