From 5c092dedafb9edeea4a7688593b16a209afea7c7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 18:53:16 +0000 Subject: [PATCH 1/2] Skip seeder on retry instead of clearing ChangeTracker in DatabaseCreators Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/b8d55ff4-793c-42c8-83b9-9b5536e7bece Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../Storage/Internal/CosmosDatabaseCreator.cs | 19 ++++++++---------- .../Storage/RelationalDatabaseCreator.cs | 20 +++++++++---------- 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs index 00c282e6907..8e80d1e6030 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs @@ -66,20 +66,13 @@ public virtual Task EnsureCreatedAsync(CancellationToken cancellationToken var created = new StrongBox(false); var dataInserted = new StrongBox(false); - var retrying = new StrongBox(false); + var seeded = new StrongBox(false); return _executionStrategy.ExecuteAsync( - (Creator: this, Created: created, DataInserted: dataInserted, Retrying: retrying), + (Creator: this, Created: created, DataInserted: dataInserted, Seeded: seeded), static async (_, state, ct) => { var creator = state.Creator; - if (state.Retrying.Value) - { - creator._currentContext.Context.ChangeTracker.Clear(); - } - - state.Retrying.Value = true; - if (!state.DataInserted.Value) { var model = creator._designTimeModel.Model; @@ -101,8 +94,12 @@ static async (_, state, ct) => } } - await creator.SeedDataAsync(state.Created.Value, cancellationToken: ct) - .ConfigureAwait(false); + if (!state.Seeded.Value) + { + await creator.SeedDataAsync(state.Created.Value, cancellationToken: ct) + .ConfigureAwait(false); + state.Seeded.Value = true; + } return state.Created.Value; }, verifySucceeded: null, cancellationToken); diff --git a/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs b/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs index 3fbad717c5d..1dcba730f78 100644 --- a/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs +++ b/src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs @@ -258,16 +258,14 @@ public virtual bool EnsureCreated() } return Dependencies.ExecutionStrategy.Execute( - (Creator: this, Created: operationsPerformed, Retrying: new StrongBox(false)), + (Creator: this, Created: operationsPerformed, Seeded: new StrongBox(false)), static (context, state) => { - if (state.Retrying.Value) + if (state.Seeded.Value) { - context.ChangeTracker.Clear(); + return state.Created; } - state.Retrying.Value = true; - var coreOptionsExtension = state.Creator.Dependencies.ContextOptions.FindExtension(); @@ -283,6 +281,8 @@ public virtual bool EnsureCreated() throw new InvalidOperationException(CoreStrings.MissingSeeder); } + state.Seeded.Value = true; + return state.Created; }, verifySucceeded: null); } @@ -324,16 +324,14 @@ public virtual async Task EnsureCreatedAsync(CancellationToken cancellatio } return await Dependencies.ExecutionStrategy.ExecuteAsync( - (Creator: this, Created: operationsPerformed, Retrying: new StrongBox(false)), + (Creator: this, Created: operationsPerformed, Seeded: new StrongBox(false)), static async (context, state, ct) => { - if (state.Retrying.Value) + if (state.Seeded.Value) { - context.ChangeTracker.Clear(); + return state.Created; } - state.Retrying.Value = true; - var coreOptionsExtension = state.Creator.Dependencies.ContextOptions.FindExtension(); @@ -350,6 +348,8 @@ static async (context, state, ct) => throw new InvalidOperationException(CoreStrings.MissingSeeder); } + state.Seeded.Value = true; + return state.Created; }, verifySucceeded: null, cancellationToken).ConfigureAwait(false); } From 4cdf8d2a345de779cdecdd93dd2500c82cd9e602 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 14 May 2026 19:07:49 +0000 Subject: [PATCH 2/2] Apply same skip-seeder-on-retry logic in Migrate(Async)Implementation Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/53caa518-e215-4fea-920f-52c1924ed8e2 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../EFCore.Relational.baseline.json | 2 +- .../Migrations/Internal/Migrator.cs | 16 ++++++---------- .../Migrations/MigrationExecutionState.cs | 4 ++-- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/EFCore.Relational/EFCore.Relational.baseline.json b/src/EFCore.Relational/EFCore.Relational.baseline.json index 9e5f52bc2f0..7cb5e6a6021 100644 --- a/src/EFCore.Relational/EFCore.Relational.baseline.json +++ b/src/EFCore.Relational/EFCore.Relational.baseline.json @@ -7921,7 +7921,7 @@ "Member": "int LastCommittedCommandIndex { get; set; }" }, { - "Member": "bool SeedingAttempted { get; set; }" + "Member": "bool SeedingCompleted { get; set; }" }, { "Member": "Microsoft.EntityFrameworkCore.Storage.IDbContextTransaction? Transaction { get; set; }" diff --git a/src/EFCore.Relational/Migrations/Internal/Migrator.cs b/src/EFCore.Relational/Migrations/Internal/Migrator.cs index 1ec0609d7b1..5008483fdbe 100644 --- a/src/EFCore.Relational/Migrations/Internal/Migrator.cs +++ b/src/EFCore.Relational/Migrations/Internal/Migrator.cs @@ -192,13 +192,11 @@ private bool MigrateImplementation( var seed = coreOptionsExtension.Seeder; if (seed != null) { - if (state.SeedingAttempted) + if (!state.SeedingCompleted) { - context.ChangeTracker.Clear(); + seed(context, state.AnyOperationPerformed); + state.SeedingCompleted = true; } - - state.SeedingAttempted = true; - seed(context, state.AnyOperationPerformed); } else if (coreOptionsExtension.AsyncSeeder != null) { @@ -334,13 +332,11 @@ await _migrationCommandExecutor.ExecuteNonQueryAsync( var seedAsync = coreOptionsExtension.AsyncSeeder; if (seedAsync != null) { - if (state.SeedingAttempted) + if (!state.SeedingCompleted) { - context.ChangeTracker.Clear(); + await seedAsync(context, state.AnyOperationPerformed, cancellationToken).ConfigureAwait(false); + state.SeedingCompleted = true; } - - state.SeedingAttempted = true; - await seedAsync(context, state.AnyOperationPerformed, cancellationToken).ConfigureAwait(false); } else if (coreOptionsExtension.Seeder != null) { diff --git a/src/EFCore.Relational/Migrations/MigrationExecutionState.cs b/src/EFCore.Relational/Migrations/MigrationExecutionState.cs index ff3e82d15ba..1eee5856f56 100644 --- a/src/EFCore.Relational/Migrations/MigrationExecutionState.cs +++ b/src/EFCore.Relational/Migrations/MigrationExecutionState.cs @@ -34,7 +34,7 @@ public sealed class MigrationExecutionState public IDbContextTransaction? Transaction { get; set; } /// - /// Indicates whether seeding has been attempted. + /// Indicates whether seeding has been completed. /// - public bool SeedingAttempted { get; set; } + public bool SeedingCompleted { get; set; } }