{"record":{"id":"afce015eb3424b79","repo":"dotnet/efcore","slug":"the-foreign-keys-foreignkeyproperties1-on-enti-afce01","errorCode":null,"errorMessage":"The foreign keys {foreignKeyProperties1} on '{entityType1}' and {foreignKeyProperties2} on '{entityType2}' are both mapped to '{table}.{foreignKeyName}', but referencing different principal tables ('{principalTable1}' and '{principalTable2}').","messagePattern":"The foreign keys (.+?) on '(.+?)' and (.+?) on '(.+?)' are both mapped to '(.+?)\\.(.+?)', but referencing different principal tables \\('(.+?)' and '(.+?)'\\)\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs","lineNumber":67,"sourceCode":"                        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\n            || duplicateForeignKey.PrincipalKey.Properties.GetColumnNames(principalTable.Value)\n                is not { } duplicatePrincipalColumns)\n        {\n            return shouldThrow\n                ? throw new InvalidOperationException(\n                    RelationalStrings.DuplicateForeignKeyPrincipalTableMismatch(\n                        foreignKey.Properties.Format(),\n                        foreignKey.DeclaringEntityType.DisplayName(),\n                        duplicateForeignKey.Properties.Format(),\n                        duplicateForeignKey.DeclaringEntityType.DisplayName(),\n                        foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),\n                        principalTable.HasValue\n                            ? foreignKey.GetConstraintName(storeObject, principalTable.Value)\n                            : foreignKey.GetDefaultName(),\n                        principalType.GetSchemaQualifiedTableName(),\n                        duplicatePrincipalType.GetSchemaQualifiedTableName()))\n                : false;\n        }\n\n        if (!columnNames.SequenceEqual(duplicateColumnNames))\n        {\n            return shouldThrow\n                ? throw new InvalidOperationException(","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs#L49-L85","documentation":"Thrown by AreCompatible when two foreign keys share a name and are declared on the same dependent table, but reference different principal tables. A single database FK constraint can only point at one principal table, so EF rejects the ambiguous mapping.","triggerScenarios":"Two FKs on entity types sharing a dependent table resolve to one constraint name, but their PrincipalEntityType maps to a different principal table. Common in TPH/table-splitting where dependent types share a row but point at different principals.","commonSituations":"Table-splitting or TPH where one shared table has FKs to two different principal tables but the constraint names collide. Refactoring a principal entity to a different table after FK config was set.","solutions":["Disambiguate the constraint names with explicit HasConstraintName so each points to its own principal cleanly.","Reconcile the principal tables: if both FKs should target the same principal, fix the principal mapping.","Split the dependent entity types onto separate tables if they genuinely reference different principals.","Verify ToTable mapping for both principal entity types is what you intended."],"exampleFix":"// before (OrderDetail shares table; FKs to Order vs Invoice, same constraint name)\nmodelBuilder.Entity<OrderDetail>().HasOne(d => d.Order)\n    .WithMany().HasForeignKey(d => d.OrderId).HasConstraintName(\"FK_Detail_Principal\");\nmodelBuilder.Entity<OrderDetail>().HasOne(d => d.Invoice)\n    .WithMany().HasForeignKey(d => d.InvoiceId).HasConstraintName(\"FK_Detail_Principal\");\n\n// after\nmodelBuilder.Entity<OrderDetail>().HasOne(d => d.Order)\n    .WithMany().HasForeignKey(d => d.OrderId).HasConstraintName(\"FK_Detail_Order\");\nmodelBuilder.Entity<OrderDetail>().HasOne(d => d.Invoice)\n    .WithMany().HasForeignKey(d => d.InvoiceId).HasConstraintName(\"FK_Detail_Invoice\");","handlingStrategy":"validation","validationCode":"// Verify FKs sharing a name also share the principal table\nforeach (var g in modelBuilder.Model.GetEntityTypes().SelectMany(t => t.GetForeignKeys())\n             .GroupBy(fk => fk.GetConstraintName()))\n{\n    var principalTables = g.Select(fk => fk.PrincipalEntityType.GetSchemaQualifiedTableName()).Distinct();\n    if (principalTables.Count() > 1)\n        throw new InvalidOperationException($\"FK {g.Key} targets multiple principal tables.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When reusing an FK constraint name, ensure all instances target the same principal table.","Give FKs to different principals distinct constraint names.","Validate the model in tests to catch principal-table mismatches before runtime."],"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"}