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?
User contributions licensed under CC BY-SA 3.0