dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.8k stars 3.2k forks source link

PendingModelChangesWarning exception thrown when upgrading to .NET 9 #35158

Open sebastianbk opened 1 day ago

sebastianbk commented 1 day ago

We just migrated from .NET 8 to .NET 9, following the migration guide provided by the ASP.NET Core team.

After having completed the steps of the guide and upgraded all SDK and package references to 9.0, we ran into the following exception when running the app.

Unhandled exception. System.InvalidOperationException: An error was generated for warning 'Microsoft.EntityFrameworkCore.Migrations.PendingModelChangesWarning': The model for context 'WasDbContext' has pending changes. Add a new migration before updating the database. This exception can be suppressed or logged by passing event ID 'RelationalEventId.PendingModelChangesWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.
   at Microsoft.EntityFrameworkCore.Diagnostics.EventDefinition`1.Log[TLoggerCategory](IDiagnosticsLogger`1 logger, TParam arg)
   at Microsoft.EntityFrameworkCore.Diagnostics.RelationalLoggerExtensions.PendingModelChangesWarning(IDiagnosticsLogger`1 diagnostics, Type contextType)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Internal.NpgsqlMigrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade)
   at Program.<Main>$(String[] args) in /Users/<REDACTED>/Program.cs:line 220

The exception is thrown in the following code block, which sits in Program.cs after the var app = builder.Build(); statement.

using (var scope = app.Services.CreateScope())
{
    var dbFactory = scope.ServiceProvider.GetRequiredService<IDbContextFactory<WasDbContext>>();
    using (var context = dbFactory.CreateDbContext())
    {
        // Apply any outstanding migrations
        context.Database.Migrate();
    }
}

The code block above has worked without any issues from .NET 6.0 through .NET 8.0.

There are no outstanding changes/migrations in our project. We branched out from our main branch (on .NET 8), which builds without any issues, so we are very puzzled by this error.

Is this a bug in the newly released version of EF Core or are we missing something in our migration?


EF Core version: 9.0.0 Database provider: Npgsql.EntityFrameworkCore.PostgreSQL 9.0.1 Target framework: .NET 9.0 Operating system: macOS Sonoma 14.6.1 IDE: JetBrains Rider 2024.3

wstaelens commented 1 day ago

same with sql server, await context.Database.MigrateAsync(); after updating from .net 8 to .net 9.

wstaelens commented 1 day ago

@sebastianbk

when doing this:

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);

            optionsBuilder.ConfigureWarnings(warnings => warnings.Log(RelationalEventId.PendingModelChangesWarning));

        }

the update-database works again

taken from here:

https://github.com/dotnet/efcore/issues/34431#issuecomment-2413845935

sebastianbk commented 1 day ago

Hi @wstaelens. I tried that and it works. Thanks for that.

However, I still believe there is an underlying bug here. This exception is not supposed to be thrown in the first place. There are not pending model changes.

ChrisJollyAU commented 1 day ago

See also #35110

AndriySvyryd commented 1 day ago

Can you provide a runnable repro project?

rudiv commented 21 hours ago

I can't find information about this change anywhere in What's New nor Breaking Changes. We had a changes that mean a migration needs to be generated in our code, so the "warning" is correct, but this is not a warning, it's a straight up error.

The fact that this works in EF Core 8.0 and not EF Core 9.0 seems like a breaking change or regression rather than something that should just be thrown in. I get the motivation behind it being that it could cause "hard to track runtime errors", but it's not an excuse to break compatibility surely?

Changing this to be an actual warning (ie. something shown at startup) would make much more sense, as it's really down to the user to handle it.