Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection

0

My DbContext is being disposed at the first call to it from my application logic.

I have a project that is structured like this. RootFolder ---DbContextProject //This is a .Net class library project ---ModelsProject //This is a .Net class library project ---InterfacesProject //This is a .Net class library project ---ApplicationLogicProject //This is a .Net class library project ---StartupProject //This is a web project I have wired up everything and is working properly but i now wanted to seed my database for testing then I got this error

System.ObjectDisposedException
  HResult = 0x80131622
  Message=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.
1 Object name: 'CBTDbContext'.
2   Source=Microsoft.EntityFrameworkCore
3   StackTrace:
4    at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed()
5    at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
6    at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__53.MoveNext()
7    at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
8    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
9    at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
10   at CBTSoftware.Services.QuestionService.<Insert>d__25.MoveNext() in C:\Users\Average\source\repos\MySoftware\MySoftware.Services\GeometryService.cs:line 285
11   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
12   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
13   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
14   at CBTSoftware.Web.Host.DbInitializer.<InitializeAsync>d__1.MoveNext() in C:\Users\Average\source\repos\MySoftware\MySoftware.Web.Host\DbInitializer.cs:line 53

At first i thought it was in the DbInitializer class which I created and was calling it from my program.cs file which is in my Web startUp project. But as you can see, on line 10 of the error message, it is pointing to my Application service. So I now put a try catch block there to see if the error was actually there, and it was. the DbContext passed into the application service is being disposed at any first call to it when the program runs.

This is my DbIntializer.cs class

public static class DbInitializer
    {
        public static IGeometry _geometryService;

        public static void InitializeAsync(IGeometry geometryService)
        {
            _geometryService = geometryService;
            SeedDatabaseAsync();
        }

        private static async void SeedDatabaseAsync()
        {
        if (_geometryService.Any())
            {
                return;
            }
        var geometries = new List<Geometry>(){....Initialization goes here....};
        foreach (Geometry geo in geometries)
        {
           await _geometryService.Insert(geo);//This is the line where the outer error throws
        //The inner error is in the Application service file below
        }
    }
}

And this is the IGeometry implementation

public class GeometryService : IGeometry
    {
        private readonly ApplicationDbContext _context;
        private readonly IShape _shape;

        public QuestionService(ApplicationDbContext context, IShape shape)
        {
            _context = context;
            _shape = shape;
        }

    public async Task<GeometyDto> Insert(GeometryDto geometry)
        {
            Geometry qs = new Geometry(){...Initialization....};
            if (!Exists(qs))
            {
                _context.Geometries.Add(qs);
        //This is the try catch block I added to detect the error message
                try
                {
                    await _context.SaveChangesAsync();
                }
                catch(Exception ex)
                {
                    return null;
                }

                return await FindAsync(geometry);
            }
            return null;
        }
}

This is my Program.cs file inside the web project

public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateWebHostBuilder(args).Build();
            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    var geometryServices = services.GetRequiredService<IGeometry>();
                    DbInitializer.InitializeAsync(geometryServices);
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred while seeding the database.");
                }
            }

            host.Run();
        }
}

And this is my Startup.cs file, how I'm injectin the services

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

    // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
        //Other services are added above this point
        services.AddScoped<IGeometry, GeometryService>();
    }
    }

Why could the DependencyInjection be disposing the DbContext or InjectedService while it was meant to be created once and used through out the life time of the application as it starts, because that's what AddScoped<TInterface, TImplemetation> does?

c#
asp.net-core
asked on Stack Overflow Sep 11, 2019 by Formula12

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0