DBContext ObjectDisposedException: Cannot access disposed object in ASP.NET Core. A common cause of this error is disposing a context..

Issue Description

Entity framework operation gives below runtime error,

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: ‘EmployeeDBContext’.

This error is mostly observed in an application using the EFCore data access layer performing CRUD operation on the Database using DBContext.

Resolution

The issue “Cannot access a disposed of object” I found to be due to improper configuration of operations accessing DBContext (which I have explained below.).

The error I also found to be a bit confusing because I had all the measures mentioned in the error description.

This actually came to me as a surprise as I already had DI implemented with Scope lifetime instance of DBContext appropriately. For DI I had used Constructor injection.

Using AddDbContext(..) ensure that you are registering the DBCOntext as a scoped object. i.e every new request will use the services injected and hence the new DBContext.

Below was my implementation,

services.AddDbContext<EmployeeContext>(options =>
            {
                 options.UseSqlServer(Configuration.GetConnectionString("EmployeeDB"),
                 sqlServerOptionsAction: sqlOptions =>
                 {
                     sqlOptions.EnableRetryOnFailure();
                 });
            });

Below was my method implemented,

If using an API pipeline to configure DBContext objects then it is recommended to use dependency injection (using constructor injection) as shown below

Example:

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

Choosing the above option also meant it will be an API IoC container that will maintain the lifetime management of DBContext and other objects.

You can also use the EFCore repository – Dependency Injection of DBContext object.

Please remove any using statements if any in the code

(The below code is only intended to be used when you want to manually instantiate and dispose of any DBContext instances.)

 using (var employeeContext = new EmployeeContext())
                {
                    employeeContext.Add(value);
                    await employeeContext.SaveChangesAsync();
                }

Instead please use DI using above above-discussed approach. Let’s see below the simplified code.

                    _employeeContext.Add(value);
                    await _employeeContext.SaveChangesAsync();

_employeeContext is DI in the constructor.

However if the above alone doesn’t fix the issue, please use additional details that I had to do to resolve the issue.

I had FindAsync which is an asynchronous method but was getting called in the synchronous method, which I had to make it asynchronous (with await keyword ) as below,

Below are the changes that were done to fix the issue,

If you have Async method used in the code then Asynchronous calls propagation should be done to the entire call stack (from start to the end) – Multithreading Async and Await API – Asynchronous Programming

  • Marked the method as async
  • await the async method call
  • Return result as Task<IActionResult> instead of IActionResult

Cannot access a disposed of object

Also, DI using Constructor injection was done as below,

    [Route("api/[controller]")]
    [ApiController]
    public class EmployeeDetailsController : ControllerBase
    {
        private readonly EmployeeContext _employeeContext;
        public EmployeeDetailsController(EmployeeContext context)
        {
            _employeeContext = context;
        }
     ...
   }

If you still face any issues please follow a few additional best practices for EFCore DBContextt listed here in the below article,

Did I miss anything else in these resolution steps?

Did the above steps resolve your issue? Please sound off your comments below!

Happy Coding !!



Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.