dotnet/efcore · error · InvalidOperationException

The foreign keys on ' ' and on ' ' are both mapped to ' …

Error message

The foreign keys {foreignKeyProperties1} on '{entityType1}' and {foreignKeyProperties2} on '{entityType2}' are both mapped to '{table}.{foreignKeyName}', but with different uniqueness configurations.

What it means

Two foreign keys share a constraint name and table but one is configured as unique and the other as non-unique. The relational layer cannot map two structurally different constraints to one database object.

Solutions

  1. Make both FKs agree on uniqueness (both unique or both non-unique) by changing the relationship multiplicity on one side.
  2. Assign distinct constraint names with HasConstraintName so the two FKs map to separate database constraints.
  3. Remap one relationship to different columns so it no longer collides.
  4. Drop the redundant FK if both relationships are semantically the same.

Example fix

// before: owned (unique) FK collides with a separate non-unique FK on the same columns
modelBuilder.Entity<User>().OwnsOne(u => u.Profile);
modelBuilder.Entity<User>().HasMany(u => u.Profiles).WithOne().HasForeignKey(p => p.UserId);

// after: keep one relationship; remove the conflicting second FK or rename it
modelBuilder.Entity<User>().OwnsOne(u => u.Profile);
// or, if both are needed, give the second a distinct constraint name
modelBuilder.Entity<User>().HasMany(u => u.Profiles).WithOne().HasForeignKey(p => p.UserId)
    .HasConstraintName("FK_Profile_User_Many");
Defensive patterns

Strategy: validation

Validate before calling

// Detect uniqueness mismatch before model validation throws.
var fks = modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys());
foreach (var fk in fks)
{
    var name = fk.GetConstraintName();
    foreach (var dup in fks.Where(o => o != fk && o.GetConstraintName() == name
                                       && o.DeclaringEntityType.GetSchemaQualifiedTableName() == fk.DeclaringEntityType.GetSchemaQualifiedTableName()))
    {
        if (fk.IsUnique != dup.IsUnique)
            Console.WriteLine($"Uniqueness mismatch on constraint '{name}'.");
    }
}

Prevention

When it happens

Trigger: RelationalForeignKeyExtensions.AreCompatible with shouldThrow:true when foreignKey.IsUnique != duplicateForeignKey.IsUnique. Typical with shared ownership, TPT, or table-splitting where one path is 1:1 (unique) and another is 1:* (non-unique) but both FKs resolve to the same constraint name.

Common situations: An owned entity also participates in a regular one-to-many relationship using the same FK columns; an alternate key relationship defined alongside a primary FK; explicit HasConstraintName reuse across mismatched relationships.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/db7df2b0c1bdf486. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs:117

        {
            return shouldThrow
                ? throw new InvalidOperationException(
                    RelationalStrings.DuplicateForeignKeyPrincipalColumnMismatch(
                        foreignKey.Properties.Format(),
                        foreignKey.DeclaringEntityType.DisplayName(),
                        duplicateForeignKey.Properties.Format(),
                        duplicateForeignKey.DeclaringEntityType.DisplayName(),
                        foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),
                        foreignKey.GetConstraintName(storeObject, principalTable.Value),
                        foreignKey.PrincipalKey.Properties.FormatColumns(principalTable.Value),
                        duplicateForeignKey.PrincipalKey.Properties.FormatColumns(principalTable.Value)))
                : false;
        }

        if (foreignKey.IsUnique != duplicateForeignKey.IsUnique)
        {
            return shouldThrow
                ? throw new InvalidOperationException(
                    RelationalStrings.DuplicateForeignKeyUniquenessMismatch(
                        foreignKey.Properties.Format(),
                        foreignKey.DeclaringEntityType.DisplayName(),
                        duplicateForeignKey.Properties.Format(),
                        duplicateForeignKey.DeclaringEntityType.DisplayName(),
                        foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),
                        foreignKey.GetConstraintName(storeObject, principalTable.Value)))
                : false;
        }

        var referentialAction = RelationalModel.ToReferentialAction(foreignKey.DeleteBehavior);
        var duplicateReferentialAction = RelationalModel.ToReferentialAction(duplicateForeignKey.DeleteBehavior);
        return referentialAction != duplicateReferentialAction
            ? shouldThrow
                ? throw new InvalidOperationException(
                    RelationalStrings.DuplicateForeignKeyDeleteBehaviorMismatch(
                        foreignKey.Properties.Format(),
                        foreignKey.DeclaringEntityType.DisplayName(),

View on GitHub (pinned to 3a2006ef56)