Cannot access a disposed object in ASP.NET Core when injecting DbContext

Find the root cause of what really happened to you disposable object.

Injection

Working with ASP.NET core I have seen this error multiple times and can be hard to debug. The error can have multiple root causes. It can be a real pain to find the cause and it is sometimes fixed by only taking care of the symptoms. By finding the root cause, you can take the appropriate action in your code.

The error message is very clear:

System.ObjectDisposedException: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application.
This may occur is you are calling Dispose() on the context, or wrapping the context in a using statement.
If you are using dependency injection, you should let the dependency injection container take care of disposing context instances.
Object name: ‘Context’.

The object is disposed in your code
The simple cause could be that you have a injected object that is disposable and dispose it somewhere in your code. This can also happen when you dispose an object that uses your inject object. When you access it after it is disposed, this error is thrown. In this case you need to check all code paths. Add a breakpoints in the dispose object of the object to see when it is called.

Some code is running async
An other cause I have seen is that you handle some logic in a new thread. The main thread returns and the dependency framework disposes objects. The new thread runs after the disposal and *BAM* you have the exception. To fix this you have to manage the disposable object in you new thread separately from your main object:

Task.Run( () => { // or ThreadPool.QueueUserWorkItem(async _ => {
    using (var context = **create your new context here, handle it directly or let the DI framework do its magic**){
        foreach(var user in Users){
            email.Send(user.email);
            context.....;
            context.SaveChanges();
        }
    }
});

Using an async void instead of async Task
An other cause can be that you have an async void method that should have been an async Task. The method does not return a Task that should have been awaited before the method returned. The underlying async code will run after your thread returns. Like starting a new thread in your code, it can go right by accident. In that case it could be that you see the error only in a release build. This can be very hard to debug when you do not know where to look.

public async void FailtyMethod(){

public async Task CorrectMethod(){

Final thoughts
Fixing this error can sometimes be very frustrating. I hope the causes I described help you. Let me know if it helps if you have other causes that can help other people facing this.

Extra information
Stackoverflow: cannot-access-a-disposed-object-in-asp-net-core-when-injecting-dbcontext
Stackoverflow: wait-for-a-void-async-method

14 thoughts on “Cannot access a disposed object in ASP.NET Core when injecting DbContext”

  1. Hi, Thanks for the article. I encountered the cannot access dispose exception while I use the Task.run() inside a async method. Actually the Task.run() executes in loop for calling a service method. After the 1st call, am getting the issue, may be due to the dependency injection disposes the client after the 1st call. how to create new instance of my DI object for each service call?

    Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.