Resolving scoped services during application startup can be difficult, because there is no request and hence no scoped service.
Resolving a scoped service during application startup via app.ApplicationServices.GetService<AppDbContext>()
can cause issues, because it will be created in the scope of the global container, effectively making it a singleton with the lifetime of the application, which may lead to exceptions like Cannot access a disposed object in ASP.NET Core when injecting DbContext
.
The following pattern solves the issue by first creating a new scope and then resolving the scoped services from it, then once the work is done, disposing the scoped container.
public Configure(IApplicationBuilder app)
{
// serviceProvider is app.ApplicationServices from Configure(IApplicationBuilder app) method
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var db = serviceScope.ServiceProvider.GetService<AppDbContext>();
if (await db.Database.EnsureCreatedAsync())
{
await SeedDatabase(db);
}
}
}
This is a semi-official way of the Entity Framework core team to seed data during application startup and is reflected in the MusicStore sample application.