diff --git a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs index 1119544f93a..f4192293658 100644 --- a/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs +++ b/src/EFCore.SqlServer/Migrations/SqlServerMigrationsSqlGenerator.cs @@ -32,6 +32,9 @@ public class SqlServerMigrationsSqlGenerator : MigrationsSqlGenerator private static readonly bool UseOldBehavior32457 = AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue32457", out var enabled32457) && enabled32457; + private static readonly bool UseOldBehavior32730 = + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue32730", out var enabled32730) && enabled32730; + private IReadOnlyList _operations = null!; private int _variableCounter; @@ -1415,17 +1418,18 @@ protected override void Generate(SqlOperation operation, IModel? model, Migratio var batchBuilder = new StringBuilder(); foreach (var line in preBatched) { - if (string.IsNullOrWhiteSpace(line)) - { - continue; - } - var trimmed = line.TrimStart(); if (trimmed.StartsWith("GO", StringComparison.OrdinalIgnoreCase) && (UseOldBehavior32457 || trimmed.Length == 2 || char.IsWhiteSpace(trimmed[2]))) { + if (UseOldBehavior32730 + && string.IsNullOrWhiteSpace(line)) + { + continue; + } + var batch = batchBuilder.ToString(); batchBuilder.Clear(); diff --git a/test/EFCore.Relational.Specification.Tests/Migrations/MigrationsInfrastructureTestBase.cs b/test/EFCore.Relational.Specification.Tests/Migrations/MigrationsInfrastructureTestBase.cs index 0d1a226dcce..db77782f269 100644 --- a/test/EFCore.Relational.Specification.Tests/Migrations/MigrationsInfrastructureTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Migrations/MigrationsInfrastructureTestBase.cs @@ -72,7 +72,32 @@ public virtual void Can_apply_all_migrations() x => Assert.Equal("00000000000001_Migration1", x.MigrationId), x => Assert.Equal("00000000000002_Migration2", x.MigrationId), x => Assert.Equal("00000000000003_Migration3", x.MigrationId), - x => Assert.Equal("00000000000004_Migration4", x.MigrationId)); + x => Assert.Equal("00000000000004_Migration4", x.MigrationId), + x => Assert.Equal("00000000000005_Migration5", x.MigrationId), + x => Assert.Equal("00000000000006_Migration6", x.MigrationId), + x => Assert.Equal("00000000000007_Migration7", x.MigrationId)); + } + + [ConditionalFact] + public virtual void Can_apply_range_of_migrations() + { + using var db = Fixture.CreateContext(); + db.Database.EnsureDeleted(); + + GiveMeSomeTime(db); + + var migrator = db.GetService(); + migrator.Migrate("Migration6"); + + var history = db.GetService(); + Assert.Collection( + history.GetAppliedMigrations(), + x => Assert.Equal("00000000000001_Migration1", x.MigrationId), + x => Assert.Equal("00000000000002_Migration2", x.MigrationId), + x => Assert.Equal("00000000000003_Migration3", x.MigrationId), + x => Assert.Equal("00000000000004_Migration4", x.MigrationId), + x => Assert.Equal("00000000000005_Migration5", x.MigrationId), + x => Assert.Equal("00000000000006_Migration6", x.MigrationId)); } [ConditionalFact] @@ -100,9 +125,8 @@ public virtual void Can_revert_all_migrations() GiveMeSomeTime(db); - db.Database.Migrate(); - var migrator = db.GetService(); + migrator.Migrate("Migration5"); migrator.Migrate(Migration.InitialDatabase); var history = db.GetService(); @@ -117,15 +141,17 @@ public virtual void Can_revert_one_migrations() GiveMeSomeTime(db); - db.Database.Migrate(); - var migrator = db.GetService(); - migrator.Migrate("Migration1"); + migrator.Migrate("Migration5"); + migrator.Migrate("Migration4"); var history = db.GetService(); Assert.Collection( history.GetAppliedMigrations(), - x => Assert.Equal("00000000000001_Migration1", x.MigrationId)); + x => Assert.Equal("00000000000001_Migration1", x.MigrationId), + x => Assert.Equal("00000000000002_Migration2", x.MigrationId), + x => Assert.Equal("00000000000003_Migration3", x.MigrationId), + x => Assert.Equal("00000000000004_Migration4", x.MigrationId)); } [ConditionalFact] @@ -144,7 +170,10 @@ await history.GetAppliedMigrationsAsync(), x => Assert.Equal("00000000000001_Migration1", x.MigrationId), x => Assert.Equal("00000000000002_Migration2", x.MigrationId), x => Assert.Equal("00000000000003_Migration3", x.MigrationId), - x => Assert.Equal("00000000000004_Migration4", x.MigrationId)); + x => Assert.Equal("00000000000004_Migration4", x.MigrationId), + x => Assert.Equal("00000000000005_Migration5", x.MigrationId), + x => Assert.Equal("00000000000006_Migration6", x.MigrationId), + x => Assert.Equal("00000000000007_Migration7", x.MigrationId)); } [ConditionalFact] @@ -357,6 +386,7 @@ public MigrationsContext(DbContextOptions options) public class Foo { public int Id { get; set; } + public string Description { get; set; } } [DbContext(typeof(MigrationsContext))] @@ -370,7 +400,7 @@ protected override void Up(MigrationBuilder migrationBuilder) migrationBuilder .CreateTable( name: "Table1", - columns: x => new { Id = x.Column(), Foo = x.Column() }) + columns: x => new { Id = x.Column(), Foo = x.Column(), Description = x.Column() }) .PrimaryKey( name: "PK_Table1", columns: x => x.Id); @@ -452,4 +482,72 @@ protected override void Down(MigrationBuilder migrationBuilder) { } } + + [DbContext(typeof(MigrationsContext))] + [Migration("00000000000005_Migration5")] + private class Migration5 : Migration + { + public const string TestValue = """ + Value With + + Empty Lines + """; + + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql($"INSERT INTO Table1 (Id, Bar, Description) VALUES (-1, ' ', '{TestValue}')"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } + + [DbContext(typeof(MigrationsContext))] + [Migration("00000000000006_Migration6")] + private class Migration6 : Migration + { + public const string TestValue = """ + GO + Value With + + Empty Lines + """; + + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql($"INSERT INTO Table1 (Id, Bar, Description) VALUES (-2, ' ', '{TestValue}')"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } + + [DbContext(typeof(MigrationsContext))] + [Migration("00000000000007_Migration7")] + private class Migration7 : Migration + { + public const string TestValue = """ + GO + Value With + + GO + + Empty Lines + GO + """; + + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql($"INSERT INTO Table1 (Id, Bar, Description) VALUES (-3, ' ', '{TestValue}')"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsInfrastructureSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsInfrastructureSqlServerTest.cs index 7ce04a75909..831ebc159b0 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsInfrastructureSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsInfrastructureSqlServerTest.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Identity30.Data; +using Microsoft.Data.SqlClient; using Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal; using Microsoft.EntityFrameworkCore.TestModels.AspNetIdentity; @@ -17,6 +18,12 @@ public MigrationsInfrastructureSqlServerTest(MigrationsInfrastructureSqlServerFi { } + public override void Can_apply_all_migrations() // Issue #32826 + => Assert.Throws(() => base.Can_apply_all_migrations()); + + public override Task Can_apply_all_migrations_async() // Issue #32826 + => Assert.ThrowsAsync(() => base.Can_apply_all_migrations_async()); + public override void Can_generate_migration_from_initial_database_to_initial() { base.Can_generate_migration_from_initial_database_to_initial(); @@ -83,6 +90,7 @@ CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId]) CREATE TABLE [Table1] ( [Id] int NOT NULL, [Foo] int NOT NULL, + [Description] nvarchar(max) NOT NULL, CONSTRAINT [PK_Table1] PRIMARY KEY ([Id]) ); GO @@ -155,6 +163,57 @@ INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) COMMIT; GO +BEGIN TRANSACTION; +GO + +INSERT INTO Table1 (Id, Bar, Description) VALUES (-1, ' ', 'Value With + +Empty Lines') +GO + +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'00000000000005_Migration5', N'7.0.0-test'); +GO + +COMMIT; +GO + +BEGIN TRANSACTION; +GO + +INSERT INTO Table1 (Id, Bar, Description) VALUES (-2, ' ', 'GO +Value With + +Empty Lines') +GO + +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'00000000000006_Migration6', N'7.0.0-test'); +GO + +COMMIT; +GO + +BEGIN TRANSACTION; +GO + +INSERT INTO Table1 (Id, Bar, Description) VALUES (-3, ' ', 'GO +Value With + +GO + + +Empty Lines +GO') +GO + +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'00000000000007_Migration7', N'7.0.0-test'); +GO + +COMMIT; +GO + """, Sql, @@ -180,6 +239,7 @@ CONSTRAINT [PK___EFMigrationsHistory] PRIMARY KEY ([MigrationId]) CREATE TABLE [Table1] ( [Id] int NOT NULL, [Foo] int NOT NULL, + [Description] nvarchar(max) NOT NULL, CONSTRAINT [PK_Table1] PRIMARY KEY ([Id]) ); GO @@ -231,6 +291,39 @@ INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) VALUES (N'00000000000004_Migration4', N'7.0.0-test'); GO +INSERT INTO Table1 (Id, Bar, Description) VALUES (-1, ' ', 'Value With + +Empty Lines') +GO + +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'00000000000005_Migration5', N'7.0.0-test'); +GO + +INSERT INTO Table1 (Id, Bar, Description) VALUES (-2, ' ', 'GO +Value With + +Empty Lines') +GO + +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'00000000000006_Migration6', N'7.0.0-test'); +GO + +INSERT INTO Table1 (Id, Bar, Description) VALUES (-3, ' ', 'GO +Value With + +GO + + +Empty Lines +GO') +GO + +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'00000000000007_Migration7', N'7.0.0-test'); +GO + """, Sql, @@ -314,6 +407,7 @@ IF NOT EXISTS ( CREATE TABLE [Table1] ( [Id] int NOT NULL, [Foo] int NOT NULL, + [Description] nvarchar(max) NOT NULL, CONSTRAINT [PK_Table1] PRIMARY KEY ([Id]) ); END; @@ -435,6 +529,99 @@ INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) COMMIT; GO +BEGIN TRANSACTION; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000005_Migration5' +) +BEGIN + INSERT INTO Table1 (Id, Bar, Description) VALUES (-1, ' ', 'Value With + + Empty Lines') +END; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000005_Migration5' +) +BEGIN + INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) + VALUES (N'00000000000005_Migration5', N'7.0.0-test'); +END; +GO + +COMMIT; +GO + +BEGIN TRANSACTION; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000006_Migration6' +) +BEGIN + INSERT INTO Table1 (Id, Bar, Description) VALUES (-2, ' ', 'GO + Value With + + Empty Lines') +END; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000006_Migration6' +) +BEGIN + INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) + VALUES (N'00000000000006_Migration6', N'7.0.0-test'); +END; +GO + +COMMIT; +GO + +BEGIN TRANSACTION; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000007_Migration7' +) +BEGIN + INSERT INTO Table1 (Id, Bar, Description) VALUES (-3, ' ', 'GO + Value With + +END; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000007_Migration7' +) +BEGIN + + Empty Lines + GO') +END; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000007_Migration7' +) +BEGIN + INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) + VALUES (N'00000000000007_Migration7', N'7.0.0-test'); +END; +GO + +COMMIT; +GO + """, Sql, @@ -465,6 +652,7 @@ IF NOT EXISTS ( CREATE TABLE [Table1] ( [Id] int NOT NULL, [Foo] int NOT NULL, + [Description] nvarchar(max) NOT NULL, CONSTRAINT [PK_Table1] PRIMARY KEY ([Id]) ); END; @@ -565,6 +753,81 @@ INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) END; GO +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000005_Migration5' +) +BEGIN + INSERT INTO Table1 (Id, Bar, Description) VALUES (-1, ' ', 'Value With + + Empty Lines') +END; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000005_Migration5' +) +BEGIN + INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) + VALUES (N'00000000000005_Migration5', N'7.0.0-test'); +END; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000006_Migration6' +) +BEGIN + INSERT INTO Table1 (Id, Bar, Description) VALUES (-2, ' ', 'GO + Value With + + Empty Lines') +END; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000006_Migration6' +) +BEGIN + INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) + VALUES (N'00000000000006_Migration6', N'7.0.0-test'); +END; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000007_Migration7' +) +BEGIN + INSERT INTO Table1 (Id, Bar, Description) VALUES (-3, ' ', 'GO + Value With + +END; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000007_Migration7' +) +BEGIN + + Empty Lines + GO') +END; +GO + +IF NOT EXISTS ( + SELECT * FROM [__EFMigrationsHistory] + WHERE [MigrationId] = N'00000000000007_Migration7' +) +BEGIN + INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) + VALUES (N'00000000000007_Migration7', N'7.0.0-test'); +END; +GO + """, Sql, diff --git a/test/EFCore.Sqlite.FunctionalTests/Migrations/MigrationsInfrastructureSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Migrations/MigrationsInfrastructureSqliteTest.cs index c8c33bfc715..73ec9fb795d 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Migrations/MigrationsInfrastructureSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Migrations/MigrationsInfrastructureSqliteTest.cs @@ -64,7 +64,8 @@ public override void Can_generate_up_scripts() CREATE TABLE "Table1" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_Table1" PRIMARY KEY, - "Foo" INTEGER NOT NULL + "Foo" INTEGER NOT NULL, + "Description" TEXT NOT NULL ); INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") @@ -95,6 +96,44 @@ public override void Can_generate_up_scripts() COMMIT; +BEGIN TRANSACTION; + +INSERT INTO Table1 (Id, Bar, Description) VALUES (-1, ' ', 'Value With + +Empty Lines') + +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('00000000000005_Migration5', '7.0.0-test'); + +COMMIT; + +BEGIN TRANSACTION; + +INSERT INTO Table1 (Id, Bar, Description) VALUES (-2, ' ', 'GO +Value With + +Empty Lines') + +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('00000000000006_Migration6', '7.0.0-test'); + +COMMIT; + +BEGIN TRANSACTION; + +INSERT INTO Table1 (Id, Bar, Description) VALUES (-3, ' ', 'GO +Value With + +GO + +Empty Lines +GO') + +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('00000000000007_Migration7', '7.0.0-test'); + +COMMIT; + """, Sql, @@ -114,7 +153,8 @@ public override void Can_generate_up_scripts_noTransactions() CREATE TABLE "Table1" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_Table1" PRIMARY KEY, - "Foo" INTEGER NOT NULL + "Foo" INTEGER NOT NULL, + "Description" TEXT NOT NULL ); INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") @@ -131,6 +171,32 @@ public override void Can_generate_up_scripts_noTransactions() INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") VALUES ('00000000000004_Migration4', '7.0.0-test'); +INSERT INTO Table1 (Id, Bar, Description) VALUES (-1, ' ', 'Value With + +Empty Lines') + +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('00000000000005_Migration5', '7.0.0-test'); + +INSERT INTO Table1 (Id, Bar, Description) VALUES (-2, ' ', 'GO +Value With + +Empty Lines') + +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('00000000000006_Migration6', '7.0.0-test'); + +INSERT INTO Table1 (Id, Bar, Description) VALUES (-3, ' ', 'GO +Value With + +GO + +Empty Lines +GO') + +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('00000000000007_Migration7', '7.0.0-test'); + """, Sql,