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.73k stars 3.18k forks source link

PendingModelChangesWarning when creating new database using .NET 9 rc.1 nightly build #34431

Closed martincostello closed 2 months ago

martincostello commented 2 months ago

File a bug

I have a number of applications I am testing .NET 9 nightly builds with, and after updating them yesterday to start ingesting builds of .NET 9 rc.1 I have an application where tests are failing due to an InvalidOperationException being thrown after a new database is created.

No code changes have been made to the application, just updating to the latest .NET SDK and NuGet packages compared to the official .NET 9 preview 7 release.

The application under test creates a new database, deleting any existing database, and then performs a migration, but is now throwing an exception during migration starting that there are pending changes. There shouldn't be any pending migration as it is a newly created database.

Steps to reproduce

Clone https://github.com/martincostello/apple-fitness-workout-mapper/commit/98b0602654e923be3498a062693361d57e531e6e and run build.ps1 from the root of the repository to build the application and run the tests.

Stack trace

 [2024-08-13 21:16:55Z] fail: Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1]
       An unhandled exception has occurred while executing the request.
 System.InvalidOperationException: An error was generated for warning 'Microsoft.EntityFrameworkCore.Migrations.PendingModelChangesWarning': The model for context 'TracksContext' 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.MigrateAsync(Func`4 seed, String targetMigration, Nullable`1 lockTimeout, CancellationToken cancellationToken)
    at MartinCostello.AppleFitnessWorkoutMapper.Services.TrackImporter.ImportTracksAsync(CancellationToken cancellationToken) in /_/src/AppleFitnessWorkoutMapper/Services/TrackImporter.cs:line 27
    at Program.<>c.<<<Main>$>b__0_12>d.MoveNext() in /_/src/AppleFitnessWorkoutMapper/Program.cs:line 201
 --- End of stack trace from previous location ---
    at Microsoft.AspNetCore.Http.Generated.<GeneratedRouteBuilderExtensions_g>F2A4F9050321DD26474371351A8857FE053630885E7CB9BFF3B12464F0B87EE32__GeneratedRouteBuilderExtensionsCore.<>c__DisplayClass6_0.<<MapPost3>g__RequestHandler|5>d.MoveNext() in /_/artifacts/obj/AppleFitnessWorkoutMapper/release/Microsoft.AspNetCore.Http.RequestDelegateGenerator/Microsoft.AspNetCore.Http.RequestDelegateGenerator.RequestDelegateGenerator/GeneratedRouteBuilderExtensions.g.cs:line 638
 --- End of stack trace from previous location ---
    at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)

Provider and version information

EF Core version: 9.0.0-rc.1.24402.2 Database provider: Microsoft.EntityFrameworkCore.Sqlite Target framework: .NET 9.0 Operating system: GitHub Actions Linux, macOS and Windows runners IDE: None.

roji commented 2 months ago

/cc @AndriySvyryd

AndriySvyryd commented 2 months ago

@martincostello You are calling context.Database.MigrateAsync, but there are no migrations in this project. That's what the warning is about.

martincostello commented 2 months ago

So has the code just been wrong forever, but it happened to just keep working anyway before 9.0-rc.1?

AndriySvyryd commented 2 months ago

It's not wrong, that call just doesn't do anything if there are no migrations. That's why we introduced the warning.

los93sol commented 1 month ago

It's not wrong, that call just doesn't do anything if there are no migrations. That's why we introduced the warning.

I'm having the same issue. Preview 7 works fine. Brand new DB, migrations apply just fine. Change nothing but upgrade to RC1 packages, start with a brand new DB and I get this warning and no migrations apply. The behavior is definitely different on RC1 packages and very unclear/unexpected with no indication as to what is actually different.

I also attempted to create a new migration on top of my existing migrations, but that just creates a new empty migration and the problem remains. I think this issue should be re-opened and investigated further.

kmcdonald-EQIX commented 1 month ago

I'm having the same issue. Preview 7 works finebut not RC1.

2024-09-20 09:38:49 System.InvalidOperationException: An error was generated for warning 'Microsoft.EntityFrameworkCore.Migrations.PendingModelChangesWarning': The model for context 'DbContext' 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'. 2024-09-20 09:38:49 at Microsoft.EntityFrameworkCore.Diagnostics.EventDefinition1.Log[TLoggerCategory](IDiagnosticsLogger1 logger, TParam arg) 2024-09-20 09:38:49 at Microsoft.EntityFrameworkCore.Diagnostics.RelationalLoggerExtensions.PendingModelChangesWarning(IDiagnosticsLogger`1 diagnostics, Type contextType) 2024-09-20 09:38:49 at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.MigrateAsync(String targetMigration, CancellationToken cancellationToken) 2024-09-20 09:38:49 at Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Internal.NpgsqlMigrator.MigrateAsync(String targetMigration, CancellationToken cancellationToken) 2024-09-20 09:38:49 at DbMigration.Services.MigrationService.ExecuteAsync(CancellationToken stoppingToken) in C:\Users\dev\source\repos\MyApp\DbMigration\Services\MigrationService.cs:line 44 2024-09-20 09:38:49 at Microsoft.Extensions.Hosting.Internal.Host.TryExecuteBackgroundServiceAsync(BackgroundService backgroundService) 2024-09-20 09:38:49 crit: Microsoft.Extensions.Hosting.Internal.Host[10] 2024-09-20 09:38:49 The HostOptions.BackgroundServiceExceptionBehavior is configured to StopHost. A BackgroundService has thrown an unhandled exception, and the IHost instance is stopping. To avoid this behavior, configure this to Ignore; however the BackgroundService will not be restarted.

Code that fails using var dbContext = await _dbContextFactory.CreateDbContextAsync(stoppingToken); var appliedMigrations = await dbContext.Database.GetAppliedMigrationsAsync(stoppingToken); await dbContext.Database.MigrateAsync(stoppingToken);

Pease re-opened

AndriySvyryd commented 1 month ago

I also attempted to create a new migration on top of my existing migrations, but that just creates a new empty migration and the problem remains. I think this issue should be re-opened and investigated further.

@los93sol That sounds like a bug. Can you open a new issue and share a small runnable repro project?

@kmcdonald-EQIX Did you try adding a new migration?

los93sol commented 1 month ago

Unfortunately repro is not so straightforward, I have been unable to repro outside of my real project so far so I don’t know exactly what the condition is that trips it, but sounds like at least 3 people have hit it already. I ignored the “warning” on rc1 packages and it did apply the migrations so something in that diff check seems like the culprit. I also would not expect a warning to abort like this, it results in a full on unhandled exception.

Another thing I tried was dropping existing migrations and just creating a brand new one against a new DB and it failed there as well so I don’t think it’s related to any previous migrations, but specifically something in that diff method that’s out of sync with the tooling to create migrations

Ryba1986 commented 1 week ago

Unfortunately repro is not so straightforward, I have been unable to repro outside of my real project so far so I don’t know exactly what the condition is that trips it, but sounds like at least 3 people have hit it already. I ignored the “warning” on rc1 packages and it did apply the migrations so something in that diff check seems like the culprit. I also would not expect a warning to abort like this, it results in a full on unhandled exception.

Another thing I tried was dropping existing migrations and just creating a brand new one against a new DB and it failed there as well so I don’t think it’s related to any previous migrations, but specifically something in that diff method that’s out of sync with the tooling to create migrations

After setting the code below, the error stopped occurring: `.UseNpgsql(.......) .ConfigureWarnings(warnings => warnings.Log(RelationalEventId.PendingModelChangesWarning))``

los93sol commented 1 week ago

Same experience here, ignoring the warning makes it work correctly. The fact that ignoring the warning changes the behavior and multiple people have experienced it now points at a problem in that diff method.

AndriySvyryd commented 1 week ago

Same experience here, ignoring the warning makes it work correctly. The fact that ignoring the warning changes the behavior and multiple people have experienced it now points at a problem in that diff method.

I'm not sure I follow. Ignoring the warning means that the exception shouldn't be thrown anymore, it doesn't change any other behavior.

To be able to investigate the underlying issue we need a repro project.

yudielcurbelo commented 1 week ago

I have the following code that runs in the Program.cs

using var scope = app.Services.CreateScope();
var context = scope.ServiceProvider.GetRequiredService<DbContextName>();

context.Database.Migrate();

I have one migration pending that has been created but not applied, and I'm getting the same exception. The migration is not being applied because of the exception.

Ignoring the exception will allow the project to apply the pending migration correctly.

options.ConfigureWarnings(warnings => { warnings.Log(RelationalEventId.PendingModelChangesWarning); });

This is not a permanent fix, but it applies the migration correctly.

c5racing commented 1 week ago

I can only reproduce this as the warning says. My model that is currently in code does not match the model that the migration is built off of.

sbwalker commented 1 day ago

I have the same problem when migrating Oqtane (https://github.com/oqtane/oqtane.framework) to .NET 9

An Error Occurred Provisioning The Master Database. This Is Usually Related To The Master Database Not Being In A Supported State. System.InvalidOperationException: An error was generated for warning 'Microsoft.EntityFrameworkCore.Migrations.PendingModelChangesWarning': The model for context 'MasterDBContext' 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.EventDefinition1.Log[TLoggerCategory](IDiagnosticsLogger1 logger, TParam arg) at Microsoft.EntityFrameworkCore.Diagnostics.RelationalLoggerExtensions.PendingModelChangesWarning(IDiagnosticsLogger`1 diagnostics, Type contextType) at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration) at Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade) at Oqtane.Infrastructure.DatabaseManager.MigrateMaster(InstallConfig install) in C:\Source\Projects\oqtane.framework\Oqtane.Server\Infrastructure\DatabaseManager.cs:line 271

using (var masterDbContext = new MasterDBContext(new DbContextOptions<MasterDBContext>(), null, _config))
{
    AddEFMigrationsHistory(sql, install.ConnectionString, install.DatabaseType, "", true);
    // push latest model into database
    masterDbContext.Database.Migrate();
    result.Success = true;
}

This logic has worked in every .NET Core release from 3.1 to 8.0 - however it is throwing an exception in .NET 9.

Suppressing the exception resolved the issue and allowed the migrations to be executed successfully.

            database.UseDatabase(optionsBuilder, connectionString)
                .ConfigureWarnings(warnings => warnings.Log(RelationalEventId.PendingModelChangesWarning));

This feels like a hack.

AndriySvyryd commented 1 day ago

@sbwalker Did you try creating a new migration?

sbwalker commented 1 day ago

@AndriySvyryd all of the migration classes are included in the application (https://github.com/oqtane/oqtane.framework/tree/dev/Oqtane.Server/Migrations/Master) providing a seamless installation and upgrade experience (for SQL Server, SQLite, MySQL, PostgreSQL)

Image

It is not clear what you mean by "creating a new migration"? The existing migration classes were created manually without using any command line tools, etc... This is necessary because Oqtane is multi-tenant and requires specific conventions for DbContext to determine how a tenant maps to a specific database. I would certainly hope that I would not need to recreate any Migration classes... if that were true, it would mean that there was a major breaking change in EF Core.

AndriySvyryd commented 22 hours ago

The existing migration classes were created manually without using any command line tools, etc...

I see. Then indeed this is a false positive, the warning is only intended for applications using ef tools to create the migrations. You can safely .Ignore it