{"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/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs#L49-L85","documentation":"Two foreign keys are mapped to the same constraint on the same table but reference different principal tables, which is impossible for a single FK constraint. AreCompatible throws DuplicateForeignKeyPrincipalTableMismatch when the principal StoreObjectIdentifiers differ or cannot be resolved.","triggerScenarios":"Two FKs on the same table both manually named the same via HasConstraintName but pointing at different principal entities/tables; refactor that changed which entity an FK targets without renaming the constraint.","commonSituations":"Two relationships on one entity (e.g. OwnerId and CustomerId) where the developer forced the same FK constraint name; TPH inheritance where base and derived declare FKs that collide.","solutions":["Remove the shared HasConstraintName override so each FK gets a distinct default name based on its principal.","If overrides are intentional, ensure each name is unique per principal-table combination.","Verify the principal entity of each relationship is the one you expect (check HasOne/WithMany targets)."],"exampleFix":"// before\nmodelBuilder.Entity<Loan>()\n    .HasOne(l => l.Account).WithMany().HasForeignKey(l => l.AccountId)\n    .HasConstraintName(\"FK_Account\");\nmodelBuilder.Entity<Loan>()\n    .HasOne(l => l.Branch).WithMany().HasForeignKey(l => l.BranchId)\n    .HasConstraintName(\"FK_Account\");\n\n// after\nmodelBuilder.Entity<Loan>()\n    .HasOne(l => l.Branch).WithMany().HasForeignKey(l => l.BranchId)\n    .HasConstraintName(\"FK_Loan_Branch\");","handlingStrategy":"validation","validationCode":"// Ensure FKs sharing a name on the same table point to the same principal table\nvar conflicts = modelBuilder.Model.GetEntityTypes()\n    .SelectMany(e => e.GetDeclaredForeignKeys())\n    .GroupBy(fk => (fk.GetConstraintName(), fk.DeclaringEntityType.GetSchemaQualifiedTableName()))\n    .Where(g => g.Select(fk => fk.PrincipalEntityType.GetSchemaQualifiedTableName()).Distinct().Count() > 1);\nif (conflicts.Any()) throw new InvalidOperationException(\"FKs sharing a constraint name reference different principal tables.\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When two relationships share a constraint name, confirm they target the same principal entity/table.","Prefer removing HasConstraintName overrides so EF computes distinct names from principal + properties."],"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"}