A note from documentation on the call to db.Database.EnsureCreated():
Note that this API does not use migrations to create the database. In
addition, the database that is created cannot be later updated using
migrations. If you are targeting a relational database and using
migrations, you can use the DbContext.Database.Migrate() method to
ensure the database is created and all migrations are applied.
You may just want to call db.Database.Migrate().
Comment taken from source found above declaration here.
Based on the answer of @steamrolla I would propose the following improvement:
public static class EnsureMigration
{
public static void EnsureMigrationOfContext<T>(this IApplicationBuilder app) where T:DbContext
{
var context = app.ApplicationServices.GetService<T>();
context.Database.Migrate();
}
}
With this you can also ensure the migration of different contexts, e.g. if you have a Identity database.
This is a slight correction to the previous answer which created an extension method. It fixes the error that is thrown the way it was written.
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Builder;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace MyApp.Extensions
{
public static class IApplicationBuilderExtensions
{
public static void SyncMigrations<T>(this IApplicationBuilder app) where T : DbContext
{
using (var serviceScope = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<T>();
context.Database.Migrate();
}
}
}
}
This works for me in ASP.NET Core 3.1, simply injecting the db context as a parameter to the existing Configure method after registering it in the ConfigureServices method.
The culprit of IStartupFilter is that it only allows synchronous execution of code. For database migrations this is not an issue since we have a synchronous Migrate() method.
Starting .NET Core 2 using C# 7.1, you can have an asynchronous Main method to your app, so you can call all initialization logic before you run the host, right after it has finished building:
public class Program
{
public static async Task Main(string[] args)
{
//first build
var host = CreateHostBuilder(args).Build();
//initialize
using (var serviceScope = host.Services.CreateScope())
{
var serviceProvider = serviceScope.ServiceProvider;
var isDevelopment =
serviceProvider.GetRequiredService<IWebHostEnvironment>().IsDevelopment();
using var context = serviceProvider.GetRequiredService<AppDbContext>();
if (isDevelopment)
await context.Database.EnsureCreatedAsync();
else
await context.Database.MigrateAsync();
if (isDevelopment)
{
using var userManager =
serviceProvider.GetRequiredService<UserManager<AppUser>>();
await userManager
.CreateAsync(new AppUser { UserName = "dummy", Email = "dummy@dumail.com" },
password: "1234");
}
}
//now run
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
In Asp core 6 you dont have StartUp , in Previous version of asp we had Configure method wich allow up to access ServiceProvider directly and then we can use GetServices to get DBcontext and then call Migrate Methods.
but now in Asp core 6 . we should create a scop and then get DBcontext object
using (var Scope = app.services.CreateScope())
{
var context = Scope.Services.GetRequireService<DBContext>();
context.Database.Migrate();
}