{"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/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs#L26-L62","documentation":"Two foreign keys resolve to the same constraint name in the database but their declaring entity types map to different tables, so they cannot share a single constraint. RelationalForeignKeyExtensions.AreCompatible throws DuplicateForeignKeyTableMismatch when GetColumnNames fails for either FK on the store object (i.e. they live on different tables).","triggerScenarios":"Two entities on different tables each have a foreign key whose computed name collides (because EF generates names from properties + principal); overriding HasConstraintName to the same value on FKs declared on different tables.","commonSituations":"Manually forcing the same constraint name across two unrelated FKs; TPT/split-table scenarios where two entity types accidentally resolve to the same FK name but on different tables; legacy naming overrides that no longer fit after a schema split.","solutions":["Let EF auto-generate constraint names, or ensure any HasConstraintName override is unique per physical table.","Inspect both foreign keys shown in the message and confirm whether they really should share a name (they should not, since they are on different tables).","Rename one constraint so the database-level names diverge."],"exampleFix":"// before\nmodelBuilder.Entity<Order>().HasOne(o => o.Customer).WithMany()\n    .HasForeignKey(o => o.CustomerId).HasConstraintName(\"FK_Customer\");\nmodelBuilder.Entity<Invoice>().HasOne(i => i.Customer).WithMany()\n    .HasForeignKey(i => i.CustomerId).HasConstraintName(\"FK_Customer\");\n\n// after\nmodelBuilder.Entity<Invoice>().HasOne(i => i.Customer).WithMany()\n    .HasForeignKey(i => i.CustomerId).HasConstraintName(\"FK_Invoice_Customer\");","handlingStrategy":"validation","validationCode":"// Ensure no two FKs on different tables share a constraint name\nvar groups = modelBuilder.Model.GetEntityTypes()\n    .SelectMany(e => e.GetDeclaredForeignKeys())\n    .Where(fk => fk.GetConstraintName() is not null)\n    .GroupBy(fk => (fk.GetConstraintName(), fk.DeclaringEntityType.GetSchemaQualifiedTableName()));\nforeach (var g in groups.Where(g => g.Count() > 1))\n{\n    // Names must be unique per table — but here the conflict is across tables sharing a name\n}\n// Stronger: assert each constraint name maps to exactly one table\nvar nameToTables = modelBuilder.Model.GetEntityTypes()\n    .SelectMany(e => e.GetDeclaredForeignKeys())\n    .Where(fk => fk.GetMappedForeignKeys(StoreObjectIdentifier.Table(fk.DeclaringEntityType.GetTableName()!)).Any())\n    .GroupBy(fk => fk.GetConstraintName())\n    .Where(g => g.Select(fk => fk.DeclaringEntityType.GetSchemaQualifiedTableName()).Distinct().Count() > 1);\nif (nameToTables.Any()) throw new InvalidOperationException(\"A FK constraint name is shared across different tables.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid forcing HasConstraintName to the same value across different tables.","Let EF auto-name constraints or include the table name in any override.","Add a startup test asserting unique constraint names per physical table."],"tags":["relational","foreign-keys","model-validation","table-mapping"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}