{"record":{"id":"4ab1bb25646d6f2e","repo":"dotnet/efcore","slug":"the-foreign-keys-foreignkeyproperties1-on-enti","errorCode":null,"errorMessage":"The foreign keys {foreignKeyProperties1} on '{entityType1}' and {foreignKeyProperties2} on '{entityType2}' are both mapped to '{foreignKeyName}', but are declared on different tables ('{table1}' and '{table2}').","messagePattern":"The foreign keys (.+?) on '(.+?)' and (.+?) on '(.+?)' are both mapped to '(.+?)', but are declared on different tables \\('(.+?)' and '(.+?)'\\)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs","lineNumber":44,"sourceCode":"        bool shouldThrow)\n    {\n        var principalType = foreignKey.PrincipalKey.IsPrimaryKey()\n            ? foreignKey.PrincipalEntityType\n            : foreignKey.PrincipalKey.DeclaringEntityType;\n        var principalTable = StoreObjectIdentifier.Create(principalType, storeObject.StoreObjectType);\n\n        var duplicatePrincipalType = duplicateForeignKey.PrincipalKey.IsPrimaryKey()\n            ? duplicateForeignKey.PrincipalEntityType\n            : duplicateForeignKey.PrincipalKey.DeclaringEntityType;\n        var duplicatePrincipalTable = StoreObjectIdentifier.Create(duplicatePrincipalType, storeObject.StoreObjectType);\n\n        var columnNames = foreignKey.Properties.GetColumnNames(storeObject);\n        var duplicateColumnNames = duplicateForeignKey.Properties.GetColumnNames(storeObject);\n        if (columnNames is null\n            || duplicateColumnNames is null)\n        {\n            return shouldThrow\n                ? throw new InvalidOperationException(\n                    RelationalStrings.DuplicateForeignKeyTableMismatch(\n                        foreignKey.Properties.Format(),\n                        foreignKey.DeclaringEntityType.DisplayName(),\n                        duplicateForeignKey.Properties.Format(),\n                        duplicateForeignKey.DeclaringEntityType.DisplayName(),\n                        principalTable.HasValue\n                            ? foreignKey.GetConstraintName(storeObject, principalTable.Value)\n                            : foreignKey.GetDefaultName(),\n                        foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),\n                        duplicateForeignKey.DeclaringEntityType.GetSchemaQualifiedTableName()))\n                : false;\n        }\n\n        if (principalTable is null\n            || duplicatePrincipalTable is null\n            || principalTable != duplicatePrincipalTable\n            || foreignKey.PrincipalKey.Properties.GetColumnNames(principalTable.Value)\n                is not { } principalColumns","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs#L26-L62","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmodelBuilder.Entity<Post>().HasOne(p => p.Blog).WithMany()\n    .HasForeignKey(p => p.BlogId).HasConstraintName(\"FK_BlogRef\");\nmodelBuilder.Entity<Comment>().HasOne(c => c.Blog).WithMany()\n    .HasForeignKey(c => c.BlogId).HasConstraintName(\"FK_BlogRef\");\n// Posts & Comments are on different tables -> mismatch\n\n// after\nmodelBuilder.Entity<Post>().HasOne(p => p.Blog).WithMany()\n    .HasForeignKey(p => p.BlogId).HasConstraintName(\"FK_Post_Blog\");\nmodelBuilder.Entity<Comment>().HasOne(c => c.Blog).WithMany()\n    .HasForeignKey(c => c.BlogId).HasConstraintName(\"FK_Comment_Blog\");","handlingStrategy":"validation","validationCode":"// Detect FK name collisions across different tables before validation\nvar groups = modelBuilder.Model.GetEntityTypes()\n    .SelectMany(t => t.GetForeignKeys())\n    .Where(fk => fk.IsConstrained)\n    .GroupBy(fk => fk.GetConstraintName());\nforeach (var g in groups.Where(g => g.Select(fk => fk.DeclaringEntityType.GetSchemaQualifiedTableName()).Distinct().Count() > 1))\n    throw new InvalidOperationException($\"FK name {g.Key} on different tables.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["efcore","foreign-key","table-mapping","model-validation","duplicate"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}