Don't clear ChangeTracker on EnsureCreated/Migrate retry; skip seeder if it already ran#38274
Don't clear ChangeTracker on EnsureCreated/Migrate retry; skip seeder if it already ran#38274Copilot wants to merge 2 commits into
Conversation
…ators Agent-Logs-Url: https://github.com/dotnet/efcore/sessions/b8d55ff4-793c-42c8-83b9-9b5536e7bece Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
|
@copilot Also apply this 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>
Done in 4cdf8d2. Removed the |
There was a problem hiding this comment.
Pull request overview
Follow-up to #38211 that walks back the ChangeTracker.Clear() calls introduced into EnsureCreated[Async] and Migrate[Async] retry paths (which were too invasive on user-tracked state) and instead prevents double-seeding by tracking whether the seeder has already completed.
Changes:
- Replace the per-retry
ChangeTracker.Clear()branches inRelationalDatabaseCreatorandCosmosDatabaseCreatorwith aSeededStrongBoxflag that short-circuits the seeder on retries. - In
Migrator, gate seeder invocation on!state.SeedingCompletedand set the flag after the seeder runs; renameMigrationExecutionState.SeedingAttempted→SeedingCompletedand update the public API baseline.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/EFCore.Relational/Storage/RelationalDatabaseCreator.cs | Replaces Retrying/ChangeTracker.Clear() with a Seeded flag short-circuit in sync/async EnsureCreated. |
| src/EFCore.Relational/Migrations/MigrationExecutionState.cs | Renames SeedingAttempted to SeedingCompleted and updates the XML doc. |
| src/EFCore.Relational/Migrations/Internal/Migrator.cs | Gates sync/async seeder execution on !SeedingCompleted and sets the flag after seeding. |
| src/EFCore.Relational/EFCore.Relational.baseline.json | Updates API baseline for the property rename. |
| src/EFCore.Cosmos/Storage/Internal/CosmosDatabaseCreator.cs | Removes retry-clear logic and adds Seeded flag guarding SeedDataAsync. |
Comments suppressed due to low confidence (1)
src/EFCore.Relational/Migrations/Internal/Migrator.cs:339
- Same issue as in
MigrateImplementation:state.SeedingCompleted = trueis set before the transaction commit on line 348. If the async commit fails transiently, the retry will skip the seeder despite the seeded rows having been rolled back. The flag should be set afterCommitAsyncsucceeds, consistent with the PR description.
if (!state.SeedingCompleted)
{
await seedAsync(context, state.AnyOperationPerformed, cancellationToken).ConfigureAwait(false);
state.SeedingCompleted = true;
}
Follow-up to #38211. Calling
ChangeTracker.Clear()from insideEnsureCreated[Async]andMigrate[Async]on retry is too invasive — it wipes user-tracked state as a side effect of a transient failure elsewhere. The original concern (avoiding double-seeding when the execution strategy retries) is better addressed by simply not re-invoking the seeder once it has already completed successfully.CosmosDatabaseCreator.EnsureCreatedAsync: dropped theRetryingflag and theChangeTracker.Clear()call; added aSeededStrongBoxthat gatesSeedDataAsyncso the async seeder runs at most once across retries.RelationalDatabaseCreator.EnsureCreated/EnsureCreatedAsync: same treatment — removed the retry branch that cleared the change tracker, and short-circuit the execution-strategy callback whenSeededis already set.Migrator.MigrateImplementation/MigrateImplementationAsync: same treatment — removed the retry branch that cleared the change tracker, and skip the seeder when it has already completed.MigrationExecutionState.SeedingAttemptedis renamed toSeedingCompleted(and the API baseline updated) to reflect that the flag is only set after a successful seed.The seeded/completed flag is set only after the seeder (and, for the relational path, the surrounding transaction commit) succeeds, so a failure inside the seeder itself will still be retried.