Skip to content

Commit a5674fd

Browse files
Address review feedback: reduce SQLite section, fix exception wording, make code sample self-contained
Agent-Logs-Url: https://github.com/dotnet/EntityFramework.Docs/sessions/746024ca-0b2a-4a41-aae0-d72cadbd0353 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
1 parent f16ba9a commit a5674fd

2 files changed

Lines changed: 4 additions & 14 deletions

File tree

entity-framework/core/managing-schemas/migrations/applying.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -390,13 +390,13 @@ After clearing the lock, subsequent migration operations proceed normally. The t
390390
391391
### Migrations and explicit transactions
392392

393-
Starting with EF Core 9, calling <xref:Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.MigrateAsync*> inside an explicit transaction throws a warning by default. This is because wrapping migrations in an external transaction prevents the migration lock from being acquired, which leaves the database unprotected from concurrent migration applications. EF Core manages its own transactions internally as needed during migration.
393+
Starting with EF Core 9, calling <xref:Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.MigrateAsync*> inside an explicit transaction throws an exception by default. This is because wrapping migrations in an external transaction prevents the migration lock from being acquired, which leaves the database unprotected from concurrent migration applications. EF Core manages its own transactions internally as needed during migration.
394394

395395
If you were previously wrapping `MigrateAsync()` in an explicit transaction:
396396

397397
```csharp
398-
// This will throw a warning in EF Core 9+
399-
await strategy.ExecuteAsync(async () =>
398+
// This will throw an exception in EF Core 9+
399+
await dbContext.Database.CreateExecutionStrategy().ExecuteAsync(async () =>
400400
{
401401
await using var transaction = await dbContext.Database.BeginTransactionAsync();
402402
await dbContext.Database.MigrateAsync();

entity-framework/core/providers/sqlite/limitations.md

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -92,17 +92,7 @@ dotnet ef database update --connection "Data Source=My.db"
9292

9393
## Concurrent migrations protection
9494

95-
EF9 introduced a [migration locking mechanism](xref:core/managing-schemas/migrations/applying#migration-locking) when executing migrations. It aims to protect against multiple migration executions happening simultaneously, as that could leave the database in a corrupted state. This is one of the potential problems resulting from applying migrations at runtime using the <xref:Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.Migrate%2A> method (see [Applying migrations](xref:core/managing-schemas/migrations/applying) for more information). To mitigate this, EF creates an exclusive lock on the database before any migration operations are applied.
96-
97-
Unfortunately, SQLite does not have a built-in application locking mechanism, so EF Core creates a separate table (`__EFMigrationsLock`) and uses it for locking. A row is inserted to acquire the lock and deleted to release it when the migration completes and the seeding code finishes execution. However, if the application terminates unexpectedly during migration (for example, the process is killed), the lock may not be released. If this happens, subsequent migration attempts will wait indefinitely for the lock.
98-
99-
To resolve an abandoned lock, delete the `__EFMigrationsLock` table or its rows from the database:
100-
101-
```sql
102-
DROP TABLE "__EFMigrationsLock";
103-
```
104-
105-
For more information, see [Handling abandoned locks](xref:core/managing-schemas/migrations/applying#handling-abandoned-locks).
95+
EF9 introduced a [migration locking mechanism](xref:core/managing-schemas/migrations/applying#migration-locking) to protect against concurrent migration executions. Unlike SQL Server, SQLite doesn't have built-in application locks, so EF Core uses a `__EFMigrationsLock` table instead. If the application terminates unexpectedly, this lock may not be released; see [Handling abandoned locks](xref:core/managing-schemas/migrations/applying#handling-abandoned-locks) for details.
10696

10797
## See also
10898

0 commit comments

Comments
 (0)