Im using EF Core in a .NET 9.0 Web API project, and I was trying to implement automatic migrations on API startup. The current project makes use of Docker containers (Configured using a Docker compose file, along with other services), without success. The DB is SQL Server and it already has migrations applied (just two, applied on the first app startup), so I expected this method to bring just an empty list (in both: project and DB, has the same migrations count, the same migration names, etc) because there are no pending migrations, they're already synchronized.
The problem: It always brings migrations brings the same list of migrations as if they had never been applied.
Nothing worked for me. Here is the current implementation:
DatabaseExtension.cs:
public static IServiceCollection AddApplicationDbContexts(this IServiceCollection services, IConfiguration configuration)
{
var masterConnString = configuration["MASTERDB_CS"]
?? (configuration.GetConnectionString("MasterDb")
?? throw new InvalidOperationException("Connection string 'MasterDb' not found."));
services.AddDbContext<MasterDbContext>(options =>
options.UseSqlServer(masterConnString, x => {
x.MigrationsAssembly(typeof(MasterDbContext).Assembly.GetName().Name);
})
);
return services;
}
public static IApplicationBuilder RunDbMigrations(this IApplicationBuilder app)
{
using (var scope = app.ApplicationServices.CreateScope())
{
var dbMaster = scope.ServiceProvider.GetRequiredService<MasterDbContext>();
var pendingMigrations = dbMaster.Database.GetPendingMigrations(); // IT DOESN'T WORK
// The connection strings were checked here:
string cs = dbMaster.Database.GetConnectionString();
Console.WriteLine(!string.IsNullOrWhiteSpace(cs) ? $"Usando DB: {cs}" : "SIN CONEXION");
// An empty list is expected here (DB, Project are synchronized)
// no need to migrate anything
if (!pendingMigrations.Any())
{
Console.WriteLine("No hay migraciones pendientes...");
return app;
}
// Instead, I always receive the two migrations (an initial an another complementary one)
// so is always trying to create the DB from scratch, and it fails because it already exists
try
{
Console.WriteLine($"Aplicando migrations...");
dbMaster.Database.Migrate();
}
catch (Exception ex)
{
Console.WriteLine($"Error al aplicar migraciones!: {ex.Message}");
throw;
}
return app;
}
}
Theere are two projects in my .NET solution: The API and a class library that stores the EF Entities, migrations and contexts
In Program.cs:
// APPLICATION SETUP
builder.Services
.AddApplicationCors() // CORS
.AddApplicationDbContexts(builder.Configuration) // Databases
// ...
// ...
var app = builder.Build();
// --------------------------------- MIDDLEWARES ---------------------------------
// DB Migrations:
app.RunDbMigrations();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
What I'm missing??
I tried everything:
- My local environment pointing to a remote DB (it works there), it gets an empty list as expected (DB, and project are synchronized)
- I reviewed connection strings (I ensured the connection strings to be exactly the same)
- I also included the migrations assembly in the .UseSqlServer() configuration method for my DbContext
- Even I tested the API with Scalar (A modern Swagger) using my endpoints, creating and uptating entities, all is working normal (It means that the Backend and the DB are communicating successfully in the same docker network)
__EFMigrationsHistory(assuming you haven't changed it) migrations table in the database and compare with the migrations available in code. If it is bringing back all migrations, are you 100% sure it is reading from the same database that you think it is? And you haven't done anything like changing the context name or something that would de-sync the table from the code?services.AddDbContext<MasterDbContext>(options => ) ...line, there are no renames of contexts or migrations as well (the project development just started)