dotnet/efcore · error · InvalidOperationException

The foreign keys {foreignKeyProperties1} on '{entityType1}'

Error message

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

What it means

Thrown by AreCompatible when two foreign keys share name, tables, columns, uniqueness, and delete behavior, but differ in IsExcludedFromMigrations (one is excluded from migrations, the other is not). EF cannot decide whether to emit the constraint in migrations, so it rejects the ambiguity.

Source

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

        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(),
                        duplicateForeignKey.Properties.Format(),
                        duplicateForeignKey.DeclaringEntityType.DisplayName(),
                        foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),
                        foreignKey.GetConstraintName(storeObject, principalTable.Value),
                        referentialAction,
                        duplicateReferentialAction))
                : false
            : foreignKey.IsExcludedFromMigrations() == duplicateForeignKey.IsExcludedFromMigrations()
            || (shouldThrow
                ? throw new InvalidOperationException(
                    RelationalStrings.DuplicateForeignKeyExcludedFromMigrationsMismatch(
                        foreignKey.Properties.Format(),
                        foreignKey.DeclaringEntityType.DisplayName(),
                        duplicateForeignKey.Properties.Format(),
                        duplicateForeignKey.DeclaringEntityType.DisplayName(),
                        foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),
                        foreignKey.GetConstraintName(storeObject, principalTable.Value)))
                : false);
    }

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public static string? GetConstraintName(
        this IReadOnlyForeignKey foreignKey,

View on GitHub (pinned to dbf9771522)

Solutions

  1. Align IsExcludedFromMigrations: set both FKs to the same value (both excluded or both managed).
  2. Give the FKs distinct HasConstraintName values when exclusion must differ.
  3. Decide ownership: either let migrations manage the constraint or exclude both and manage manually.
  4. Audit shared-table FKs for exclusion consistency before reusing names.

Example fix

// before
modelBuilder.Entity<Order>().HasOne(o => o.Customer)
    .WithMany().HasForeignKey(o => o.CustomerId)
    .HasConstraintName("FK_Order_Cust");
modelBuilder.Entity<OrderHistory>().HasOne(h => h.Customer)
    .WithMany().HasForeignKey(h => h.CustomerId)
    .HasConstraintName("FK_Order_Cust")
    .IsExcludedFromMigrations(true); // shares table & name, differs

// after
modelBuilder.Entity<OrderHistory>().HasOne(h => h.Customer)
    .WithMany().HasForeignKey(h => h.CustomerId)
    .HasConstraintName("FK_OrderHistory_Cust")
    .IsExcludedFromMigrations(true);
Defensive patterns

Strategy: validation

Validate before calling

// Verify FKs sharing a name agree on IsExcludedFromMigrations
foreach (var g in allFks.GroupBy(fk => fk.GetConstraintName()))
{
    if (g.Select(fk => fk.IsExcludedFromMigrations()).Distinct().Count() > 1)
        throw new InvalidOperationException($"FK {g.Key} has mismatched migration exclusion.");
}

Prevention

When it happens

Trigger: Two sharing-table FKs with the same constraint name where one is configured IsExcludedFromMigrations(true) and the other uses the default false. Common when an FK is meant to be read-only/pre-existing (excluded) but shares a name with a managed one.

Common situations: Marking an FK as IsExcludedFromMigrations because it references a pre-existing constraint, while another shared-table relationship reuses the name without exclusion. Table-splitting setups where one side is hand-managed.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/5184dfa1c1ed80b5. Report an issue: GitHub.