Deep Analysis and Solutions for "Cannot access a disposed object" Error When Injecting DbContext in ASP.NET Core

Dec 07, 2025 · Programming · 15 views · 7.8

Keywords: ASP.NET Core | Entity Framework Core | Dependency Injection | DbContext | ObjectDisposedException

Abstract: This article provides an in-depth exploration of the "System.ObjectDisposedException: Cannot access a disposed object" error that may occur when using Entity Framework Core's DbContext via dependency injection in ASP.NET Core applications. Starting from the problem scenario, it analyzes the root cause: incorrectly resolving scoped services during application startup (e.g., data seeding), leading to premature disposal of DbContext instances. By comparing solutions across different ASP.NET Core versions (1.x, 2.0, 2.1 and later), it emphasizes the correct pattern of using IServiceScopeFactory to create independent scopes, ensuring DbContext is managed and used within its proper lifecycle. Additionally, the article covers the impact of asynchronous method return types (void vs. Task) on resource disposal, offering comprehensive code examples and best practices to help developers avoid such errors fundamentally.

Problem Background and Error Scenario

In ASP.NET Core applications, developers often use Entity Framework Core's DbContext through dependency injection (DI). However, in certain scenarios, particularly during application startup or asynchronous operations, the following error may occur:

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 if 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'.

This error typically arises when attempting to access a DbContext instance that has already been disposed. For example, when injecting IValidationService in a controller and calling its ValidateAsync method, if the DbContext used internally has been disposed, this exception is thrown.

Root Cause Analysis

The fundamental cause of the error is improper lifecycle management of DbContext. In ASP.NET Core, DbContext is usually registered as a scoped service, meaning its instance is unique per HTTP request and is automatically disposed at the end of the request. However, during application startup (e.g., in Program.Main or Startup.Configure methods), there is no existing request scope. If DbContext is resolved directly from ApplicationServices, it leads to the following issues:

Additionally, improper return types in asynchronous operations (e.g., using async void instead of async Task) can cause the context to be disposed unexpectedly before the operation completes, leading to this error.

Solution: Using IServiceScopeFactory to Create Independent Scopes

To avoid the above issues, the correct approach is to create an independent scope during application startup and resolve and use DbContext within that scope. Below are solutions tailored for different ASP.NET Core versions.

ASP.NET Core 1.x Version

In ASP.NET Core 1.x, you can use the following pattern in the Startup.Configure method:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // Other configurations...
    
    using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
    {
        var context = serviceScope.ServiceProvider.GetService<MyDbContext>();
        // Perform data seeding or other initialization operations
        SeedDataAsync(context).GetAwaiter().GetResult();
    }
}

This method ensures that DbContext is created and used within an independent scope, without interfering with instances in subsequent requests.

ASP.NET Core 2.0 and Later Versions

Starting from ASP.NET Core 2.0, it is recommended to perform data seeding in the Program.Main method to ensure initialization completes before the application runs. Here is a typical example:

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();
        
        // Create a scope and execute seeding
        using (var scope = host.Services.CreateScope())
        {
            var context = scope.ServiceProvider.GetRequiredService<MyDbContext>();
            SeedDataAsync(context).GetAwaiter().GetResult();
        }
        
        host.Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

In ASP.NET Core 2.1 and later, you can also use the IWebHost.Seed() extension method for more modular code:

public static IWebHost Seed(this IWebHost webhost)
{
    using (var scope = webhost.Services.CreateScope())
    {
        var context = scope.ServiceProvider.GetRequiredService<MyDbContext>();
        SeedDataAsync(context).GetAwaiter().GetResult();
    }
    return webhost;
}

// Usage in Main method
public static void Main(string[] args)
{
    CreateWebHostBuilder(args)
        .Build()
        .Seed()
        .Run();
}

Additional Considerations

Beyond scope management, the following factors may also lead to similar ObjectDisposedException errors:

Conclusion

Properly handling the lifecycle of DbContext in ASP.NET Core is key to avoiding the "Cannot access a disposed object" error. By using IServiceScopeFactory to create independent scopes, you can ensure DbContext is instantiated and disposed within the correct context. Additionally, paying attention to asynchronous operation return types and service registration configurations can further mitigate potential issues. Following these best practices enables developers to build more stable and maintainable applications.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.