dotnet/efcore · error · InvalidOperationException
The foreign keys {foreignKeyProperties1} on '{entityType1}'
Error message
The foreign keys {foreignKeyProperties1} on '{entityType1}' and {foreignKeyProperties2} on '{entityType2}' are both mapped to '{foreignKeyName}', but are declared on different tables ('{table1}' and '{table2}'). What it means
Thrown by RelationalForeignKeyExtensions.AreCompatible when two foreign keys resolve to the same constraint name but their declaring entity types map to different tables. EF cannot create one database FK constraint spanning two different dependent tables, so it rejects the conflict during relational model validation.
Source
Thrown at src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs:44
bool shouldThrow)
{
var principalType = foreignKey.PrincipalKey.IsPrimaryKey()
? foreignKey.PrincipalEntityType
: foreignKey.PrincipalKey.DeclaringEntityType;
var principalTable = StoreObjectIdentifier.Create(principalType, storeObject.StoreObjectType);
var duplicatePrincipalType = duplicateForeignKey.PrincipalKey.IsPrimaryKey()
? duplicateForeignKey.PrincipalEntityType
: duplicateForeignKey.PrincipalKey.DeclaringEntityType;
var duplicatePrincipalTable = StoreObjectIdentifier.Create(duplicatePrincipalType, storeObject.StoreObjectType);
var columnNames = foreignKey.Properties.GetColumnNames(storeObject);
var duplicateColumnNames = duplicateForeignKey.Properties.GetColumnNames(storeObject);
if (columnNames is null
|| duplicateColumnNames is null)
{
return shouldThrow
? throw new InvalidOperationException(
RelationalStrings.DuplicateForeignKeyTableMismatch(
foreignKey.Properties.Format(),
foreignKey.DeclaringEntityType.DisplayName(),
duplicateForeignKey.Properties.Format(),
duplicateForeignKey.DeclaringEntityType.DisplayName(),
principalTable.HasValue
? foreignKey.GetConstraintName(storeObject, principalTable.Value)
: foreignKey.GetDefaultName(),
foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),
duplicateForeignKey.DeclaringEntityType.GetSchemaQualifiedTableName()))
: false;
}
if (principalTable is null
|| duplicatePrincipalTable is null
|| principalTable != duplicatePrincipalTable
|| foreignKey.PrincipalKey.Properties.GetColumnNames(principalTable.Value)
is not { } principalColumnsView on GitHub (pinned to dbf9771522)
Solutions
- Set distinct HasConstraintName values on the colliding foreign keys so they do not collapse to one name.
- Ensure the two entity types that should share a constraint actually map to the same dependent table (table splitting/TPH) if that was the intent.
- Adjust table mapping so the FKs land on the same table if they are meant to be one constraint.
- Audit all foreign keys whose GetConstraintName is identical across different tables.
Example fix
// before
modelBuilder.Entity<Post>().HasOne(p => p.Blog).WithMany()
.HasForeignKey(p => p.BlogId).HasConstraintName("FK_BlogRef");
modelBuilder.Entity<Comment>().HasOne(c => c.Blog).WithMany()
.HasForeignKey(c => c.BlogId).HasConstraintName("FK_BlogRef");
// Posts & Comments are on different tables -> mismatch
// after
modelBuilder.Entity<Post>().HasOne(p => p.Blog).WithMany()
.HasForeignKey(p => p.BlogId).HasConstraintName("FK_Post_Blog");
modelBuilder.Entity<Comment>().HasOne(c => c.Blog).WithMany()
.HasForeignKey(c => c.BlogId).HasConstraintName("FK_Comment_Blog"); Defensive patterns
Strategy: validation
Validate before calling
// Detect FK name collisions across different tables before validation
var groups = modelBuilder.Model.GetEntityTypes()
.SelectMany(t => t.GetForeignKeys())
.Where(fk => fk.IsConstrained)
.GroupBy(fk => fk.GetConstraintName());
foreach (var g in groups.Where(g => g.Select(fk => fk.DeclaringEntityType.GetSchemaQualifiedTableName()).Distinct().Count() > 1))
throw new InvalidOperationException($"FK name {g.Key} on different tables."); Prevention
- Set explicit HasConstraintName on FKs whose default names might collide.
- Avoid reusing FK constraint names across entity types mapped to different tables.
- Run model validation in a unit test to surface name collisions early.
When it happens
Trigger: Two entity types each define a foreign key whose generated/explicit constraint name collides, but the entity types are mapped to different physical tables. Triggered when EnsureRelationalModel runs compatibility checks with shouldThrow=true.
Common situations: Default FK name generation produces the same name for unrelated entity types mapped to separate tables (e.g. both FK_Blogs_Posts_Id). Custom HasConstraintName strings reused across types. Renaming a table after FKs were configured.
Related errors
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/4ab1bb25646d6f2e.
Report an issue: GitHub.