Skip to content

Commit bea4f56

Browse files
committed
Don't break transactions across batches
1 parent 9d2ce49 commit bea4f56

File tree

9 files changed

+460
-699
lines changed

9 files changed

+460
-699
lines changed

src/EFCore.Relational/Migrations/HistoryRepository.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ private IReadOnlyList<MigrationCommand> GetCreateIfNotExistsCommands()
233233
/// Gets an exclusive lock on the database.
234234
/// </summary>
235235
/// <param name="cancellationToken">A <see cref="CancellationToken" /> to observe while waiting for the task to complete.</param>
236-
///
236+
///
237237
/// <returns>An object that can be disposed to release the lock.</returns>
238238
/// <exception cref="OperationCanceledException">If the <see cref="CancellationToken" /> is canceled.</exception>
239239
public abstract Task<IMigrationsDatabaseLock> AcquireDatabaseLockAsync(CancellationToken cancellationToken = default);

src/EFCore.Relational/Migrations/Internal/MigrationCommandExecutor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public virtual Task ExecuteNonQueryAsync(
156156
CancellationToken cancellationToken = default)
157157
=> ExecuteNonQueryAsync(
158158
migrationCommands.ToList(), connection, new MigrationExecutionState(), commitTransaction: true, System.Data.IsolationLevel.Unspecified, cancellationToken);
159-
159+
160160
/// <summary>
161161
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
162162
/// the same compatibility standards as public APIs. It may be changed or removed without notice in

src/EFCore.Relational/Migrations/Internal/Migrator.cs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,7 @@ private static void GenerateSqlScript(
633633
if (!transactionStarted && !command.TransactionSuppressed)
634634
{
635635
builder
636-
.AppendLine(sqlGenerationHelper.StartTransactionStatement)
637-
.Append(sqlGenerationHelper.BatchTerminator);
636+
.AppendLine(sqlGenerationHelper.StartTransactionStatement);
638637
transactionStarted = true;
639638
}
640639

@@ -663,7 +662,10 @@ private static void GenerateSqlScript(
663662
builder.Append(command.CommandText);
664663
}
665664

666-
builder.Append(sqlGenerationHelper.BatchTerminator);
665+
if (!transactionStarted)
666+
{
667+
builder.Append(sqlGenerationHelper.BatchTerminator);
668+
}
667669
}
668670
}
669671

@@ -680,10 +682,18 @@ protected virtual IReadOnlyList<MigrationCommand> GenerateUpSql(
680682
var insertCommand = _rawSqlCommandBuilder.Build(
681683
_historyRepository.GetInsertScript(new HistoryRow(migration.GetId(), ProductInfo.GetVersion())));
682684

683-
return _migrationsSqlGenerator
684-
.Generate(migration.UpOperations, FinalizeModel(migration.TargetModel), options)
685-
.Concat([new MigrationCommand(insertCommand, _currentContext.Context, _commandLogger)])
686-
.ToList();
685+
var operations = _migrationsSqlGenerator
686+
.Generate(
687+
migration.UpOperations,
688+
FinalizeModel(migration.TargetModel),
689+
options);
690+
691+
return
692+
[
693+
.. operations,
694+
new MigrationCommand(insertCommand, _currentContext.Context, _commandLogger,
695+
transactionSuppressed: operations.Any(o => o.TransactionSuppressed)),
696+
];
687697
}
688698

689699
/// <summary>
@@ -700,11 +710,17 @@ protected virtual IReadOnlyList<MigrationCommand> GenerateDownSql(
700710
var deleteCommand = _rawSqlCommandBuilder.Build(
701711
_historyRepository.GetDeleteScript(migration.GetId()));
702712

703-
return _migrationsSqlGenerator
713+
var operations = _migrationsSqlGenerator
704714
.Generate(
705-
migration.DownOperations, previousMigration == null ? null : FinalizeModel(previousMigration.TargetModel), options)
706-
.Concat([new MigrationCommand(deleteCommand, _currentContext.Context, _commandLogger)])
707-
.ToList();
715+
migration.DownOperations,
716+
previousMigration == null ? null : FinalizeModel(previousMigration.TargetModel),
717+
options);
718+
719+
return [
720+
.. operations,
721+
new MigrationCommand(deleteCommand, _currentContext.Context, _commandLogger,
722+
transactionSuppressed: operations.Any(o => o.TransactionSuppressed))
723+
];
708724
}
709725

710726
private IModel? FinalizeModel(IModel? model)

0 commit comments

Comments
 (0)