diff --git a/src/EFCore.Design/Properties/DesignStrings.Designer.cs b/src/EFCore.Design/Properties/DesignStrings.Designer.cs
index 25ce7212218..42479c8a5b3 100644
--- a/src/EFCore.Design/Properties/DesignStrings.Designer.cs
+++ b/src/EFCore.Design/Properties/DesignStrings.Designer.cs
@@ -230,6 +230,14 @@ public static string ForeignKeyScaffoldErrorPropertyNotFound([CanBeNull] object
GetString("ForeignKeyScaffoldErrorPropertyNotFound", nameof(foreignKeyName), nameof(columnNames)),
foreignKeyName, columnNames);
+ ///
+ /// Could not scaffold the foreign key '{foreignKeyName}'. Foreign key '{existingForeignKey}' is defined on same columns targeting same key on principal table.
+ ///
+ public static string ForeignKeyWithSameFacetsExists([CanBeNull] object foreignKeyName, [CanBeNull] object existingForeignKey)
+ => string.Format(
+ GetString("ForeignKeyWithSameFacetsExists", nameof(foreignKeyName), nameof(existingForeignKey)),
+ foreignKeyName, existingForeignKey);
+
///
/// The namespace '{migrationsNamespace}' contains migrations for a different DbContext. This can result in conflicting migration names. It's recommend to put migrations for different DbContext classes into different namespaces.
///
@@ -383,7 +391,7 @@ public static string NonNullableBoooleanColumnHasDefaultConstraint([CanBeNull] o
columnName);
///
- /// The provider '{provider}' is not a Relational provider and therefore cannot be use with Migrations.
+ /// The provider '{provider}' is not a Relational provider and therefore cannot be used with Migrations.
///
public static string NonRelationalProvider([CanBeNull] object provider)
=> string.Format(
@@ -455,7 +463,7 @@ public static string ProviderReturnedNullModel([CanBeNull] object providerTypeNa
providerTypeName);
///
- /// No files were generated in directory '{outputDirectoryName}'. The following file(s) already exist and must be made writeable to continue: {readOnlyFiles}.
+ /// No files were generated in directory '{outputDirectoryName}'. The following file(s) already exist(s) and must be made writeable to continue: {readOnlyFiles}.
///
public static string ReadOnlyFiles([CanBeNull] object outputDirectoryName, [CanBeNull] object readOnlyFiles)
=> string.Format(
diff --git a/src/EFCore.Design/Properties/DesignStrings.resx b/src/EFCore.Design/Properties/DesignStrings.resx
index 3c16f317ceb..5eeca7bf272 100644
--- a/src/EFCore.Design/Properties/DesignStrings.resx
+++ b/src/EFCore.Design/Properties/DesignStrings.resx
@@ -201,6 +201,9 @@
Could not scaffold the foreign key '{foreignKeyName}'. The following columns in the foreign key could not be scaffolded: {columnNames}.
+
+ Could not scaffold the foreign key '{foreignKeyName}'. Foreign key '{existingForeignKey}' is defined on same columns targeting same key on principal table.
+
The namespace '{migrationsNamespace}' contains migrations for a different DbContext. This can result in conflicting migration names. It's recommend to put migrations for different DbContext classes into different namespaces.
@@ -369,4 +372,4 @@ Change your target project to the migrations project by using the Package Manage
Writing model snapshot to '{file}'.
-
+
\ No newline at end of file
diff --git a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs
index be28f80b28f..a651dfa2a5b 100644
--- a/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs
+++ b/src/EFCore.Design/Scaffolding/Internal/RelationalScaffoldingModelFactory.cs
@@ -748,7 +748,6 @@ protected virtual IMutableForeignKey VisitForeignKey([NotNull] ModelBuilder mode
}
var dependentEntityType = modelBuilder.Model.FindEntityType(GetEntityTypeName(foreignKey.Table));
-
if (dependentEntityType == null)
{
return null;
@@ -824,9 +823,7 @@ protected virtual IMutableForeignKey VisitForeignKey([NotNull] ModelBuilder mode
nullablePrincipalProperties.Select(tuple => tuple.column.DisplayName()).ToList()
.Aggregate((a, b) => a + "," + b)));
- nullablePrincipalProperties
- .ToList()
- .ForEach(tuple => tuple.property.IsNullable = false);
+ nullablePrincipalProperties.ForEach(tuple => tuple.property.IsNullable = false);
}
principalKey = principalEntityType.AddKey(principalProperties);
@@ -845,6 +842,15 @@ protected virtual IMutableForeignKey VisitForeignKey([NotNull] ModelBuilder mode
}
}
+ var existingForeignKey = dependentEntityType.FindForeignKey(dependentProperties, principalKey, principalEntityType);
+ if (existingForeignKey is not null)
+ {
+ _reporter.WriteWarning(
+ DesignStrings.ForeignKeyWithSameFacetsExists(foreignKey.DisplayName(), existingForeignKey.GetConstraintName()));
+
+ return null;
+ }
+
var newForeignKey = dependentEntityType.AddForeignKey(
dependentProperties, principalKey, principalEntityType);
diff --git a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs
index d9ef9744d46..6ebfb7126f1 100644
--- a/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs
+++ b/test/EFCore.Design.Tests/Scaffolding/Internal/RelationalScaffoldingModelFactoryTest.cs
@@ -1145,6 +1145,64 @@ public void It_logs_warning_for_bad_foreign_key()
childrenTable.ForeignKeys.ElementAt(0).DisplayName(), "NotPkId", "Parent")));
}
+ [ConditionalFact]
+ public void It_logs_warning_for_duplicate_foreign_key()
+ {
+ var parentTable = new DatabaseTable
+ {
+ Database = Database,
+ Name = "Parent",
+ Columns =
+ {
+ IdColumn
+ },
+ PrimaryKey = IdPrimaryKey
+ };
+ var childrenTable = new DatabaseTable
+ {
+ Database = Database,
+ Name = "Children",
+ Columns =
+ {
+ IdColumn,
+ new DatabaseColumn
+ {
+ Table = Table,
+ Name = "ParentId",
+ StoreType = "int"
+ }
+ },
+ PrimaryKey = IdPrimaryKey
+ };
+ childrenTable.ForeignKeys.Add(
+ new DatabaseForeignKey
+ {
+ Table = childrenTable,
+ Name = "FK_Foo",
+ Columns = { childrenTable.Columns.ElementAt(1) },
+ PrincipalTable = parentTable,
+ PrincipalColumns = { parentTable.Columns.ElementAt(0) }
+ });
+ childrenTable.ForeignKeys.Add(
+ new DatabaseForeignKey
+ {
+ Table = childrenTable,
+ Name = "FK_Another_Foo",
+ Columns = { childrenTable.Columns.ElementAt(1) },
+ PrincipalTable = parentTable,
+ PrincipalColumns = { parentTable.Columns.ElementAt(0) }
+ });
+
+ _factory.Create(
+ new DatabaseModel { Tables = { parentTable, childrenTable } },
+ new ModelReverseEngineerOptions());
+
+ Assert.Single(
+ _reporter.Messages, t => t.Contains(
+ "warn: "
+ + DesignStrings.ForeignKeyWithSameFacetsExists(childrenTable.ForeignKeys.ElementAt(1).DisplayName(), "FK_Foo")));
+ }
+
[ConditionalFact]
public void Unique_nullable_index_unused_by_foreign_key()
{