Skip to content

Commit 6ec78b0

Browse files
Fix redundant (string)null schema argument in ToTable snapshot generation (#38424)
Fixes #26067 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
1 parent 1a62dde commit 6ec78b0

5 files changed

Lines changed: 127 additions & 1 deletion

File tree

src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1204,7 +1204,9 @@ private void GenerateTableMapping(
12041204
}
12051205

12061206
if (schema != null
1207-
|| (schemaAnnotation != null && tableName != null))
1207+
|| (schemaAnnotation != null
1208+
&& tableName != null
1209+
&& entityType.GetDefaultSchema() != null))
12081210
{
12091211
stringBuilder
12101212
.Append(", ");

test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.ModelSnapshot.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,31 @@ public void Views_are_stored_in_the_model_snapshot()
11051105
"""),
11061106
o => Assert.Equal("EntityWithOneProperty", o.GetEntityTypes().Single().GetViewName()));
11071107

1108+
[Fact] // Issue #26067
1109+
public void ToTable_with_default_null_schema_is_not_changed_on_snapshot_round_trip()
1110+
{
1111+
// When the default schema is null, regenerating the snapshot from a model that was itself
1112+
// built from a snapshot (as happens when removing a migration) must not add a redundant
1113+
// ", (string)null" schema argument to every ToTable call.
1114+
var modelBuilder = CreateConventionalModelBuilder();
1115+
modelBuilder.HasDefaultSchema(null);
1116+
modelBuilder.Model.RemoveAnnotation(CoreAnnotationNames.ProductVersion);
1117+
modelBuilder.Entity<EntityWithOneProperty>().Ignore(e => e.EntityWithTwoProperties);
1118+
1119+
var model = modelBuilder.FinalizeModel(designTime: true, skipValidation: true);
1120+
1121+
var generator = CreateMigrationsGenerator();
1122+
var code = generator.GenerateSnapshot("RootNamespace", typeof(DbContext), "Snapshot", model);
1123+
1124+
Assert.Contains(@"b.ToTable(""EntityWithOneProperty"");", code);
1125+
Assert.DoesNotContain("(string)null", code);
1126+
1127+
var roundTrippedModel = BuildModelFromSnapshotSource(code);
1128+
var roundTrippedCode = generator.GenerateSnapshot("RootNamespace", typeof(DbContext), "Snapshot", roundTrippedModel);
1129+
1130+
Assert.Equal(code, roundTrippedCode, ignoreLineEndingDifferences: true);
1131+
}
1132+
11081133
[Fact]
11091134
public void Views_with_schemas_are_stored_in_the_model_snapshot()
11101135
=> Test(

test/EFCore.Relational.Specification.Tests/Migrations/MigrationsTestBase.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,60 @@ public virtual Task Alter_column_reset_collation()
14291429
Assert.Null(nameColumn.Collation);
14301430
});
14311431

1432+
[Fact]
1433+
public virtual async Task Convert_owned_entity_with_no_schema_to_regular_entity()
1434+
=> await Test(
1435+
common =>
1436+
{
1437+
common.HasDefaultSchema(null);
1438+
common.Entity(
1439+
"Entity", e =>
1440+
{
1441+
e.Property<int>("Id").ValueGeneratedOnAdd();
1442+
e.HasKey("Id");
1443+
e.Property<string>("Name");
1444+
e.ToTable("Entity", "MySchema");
1445+
});
1446+
},
1447+
source =>
1448+
{
1449+
source.Entity(
1450+
"Entity", e =>
1451+
{
1452+
e.OwnsOne(
1453+
"Owned", "OwnedReference", o =>
1454+
{
1455+
o.Property<DateTime>("Date");
1456+
o.ToTable("Owned", (string)null);
1457+
});
1458+
});
1459+
},
1460+
target =>
1461+
{
1462+
target.Entity(
1463+
"Owned", e =>
1464+
{
1465+
e.Property<int>("EntityId").ValueGeneratedNever();
1466+
e.HasKey("EntityId");
1467+
e.Property<DateTime>("Date");
1468+
e.ToTable("Owned", (string)null);
1469+
});
1470+
},
1471+
model =>
1472+
{
1473+
Assert.Equal(2, model.Tables.Count());
1474+
1475+
var ownedTable = model.Tables.Single(t => t.Name == "Owned");
1476+
var entityTable = model.Tables.Single(t => t.Name == "Entity");
1477+
1478+
if (AssertSchemaNames)
1479+
{
1480+
Assert.Equal("MySchema", entityTable.Schema);
1481+
Assert.NotEqual("MySchema", ownedTable.Schema);
1482+
}
1483+
});
1484+
1485+
#pragma warning disable EF8001 // Owned JSON entities are obsolete
14321486
[Fact]
14331487
public virtual async Task Convert_json_entities_to_regular_owned()
14341488
=> await Test(

test/EFCore.SqlServer.FunctionalTests/Migrations/MigrationsSqlServerTest.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,16 @@ FROM [sys].[columns] [c]
14501450
""");
14511451
}
14521452

1453+
public override async Task Convert_owned_entity_with_no_schema_to_regular_entity()
1454+
{
1455+
await base.Convert_owned_entity_with_no_schema_to_regular_entity();
1456+
1457+
AssertSql(
1458+
"""
1459+
ALTER TABLE [Owned] DROP CONSTRAINT [FK_Owned_Entity_EntityId];
1460+
""");
1461+
}
1462+
14531463
public override async Task Convert_json_entities_to_regular_owned()
14541464
{
14551465
await base.Convert_json_entities_to_regular_owned();

test/EFCore.Sqlite.FunctionalTests/Migrations/MigrationsSqliteTest.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,6 +1098,41 @@ public override async Task Alter_column_reset_collation()
10981098
""");
10991099
}
11001100

1101+
public override async Task Convert_owned_entity_with_no_schema_to_regular_entity()
1102+
{
1103+
await base.Convert_owned_entity_with_no_schema_to_regular_entity();
1104+
1105+
AssertSql(
1106+
"""
1107+
CREATE TABLE "ef_temp_Owned" (
1108+
"EntityId" INTEGER NOT NULL CONSTRAINT "PK_Owned" PRIMARY KEY,
1109+
"Date" TEXT NOT NULL
1110+
);
1111+
""",
1112+
//
1113+
"""
1114+
INSERT INTO "ef_temp_Owned" ("EntityId", "Date")
1115+
SELECT "EntityId", "Date"
1116+
FROM "Owned";
1117+
""",
1118+
//
1119+
"""
1120+
PRAGMA foreign_keys = 0;
1121+
""",
1122+
//
1123+
"""
1124+
DROP TABLE "Owned";
1125+
""",
1126+
//
1127+
"""
1128+
ALTER TABLE "ef_temp_Owned" RENAME TO "Owned";
1129+
""",
1130+
//
1131+
"""
1132+
PRAGMA foreign_keys = 1;
1133+
""");
1134+
}
1135+
11011136
public override async Task Convert_json_entities_to_regular_owned()
11021137
{
11031138
await base.Convert_json_entities_to_regular_owned();

0 commit comments

Comments
 (0)