dotnet/efcore · error · InvalidOperationException

The keys on ' ' and on ' ' are both mapped to ' . ', but…

Error message

The keys {keyProperties1} on '{entityType1}' and {keyProperties2} on '{entityType2}' are both mapped to '{table}.{keyName}', but with different columns ({columnNames1} and {columnNames2}).

What it means

Two keys share the same database name and table but map to different columns. A single key constraint name cannot identify two different column sets.

Solutions

  1. Give each key a distinct name via HasName(...).
  2. Map both keys to the same columns if they are meant to be the same constraint.
  3. Remove the redundant key.
  4. Audit HasName usages across entities that share a table.

Example fix

// before
modelBuilder.Entity<Order>().HasKey(o => o.Id).HasName("PK_Order");
modelBuilder.Entity<OrderSnapshot>().ToTable("Order").HasKey(s => s.SnapshotId).HasName("PK_Order");

// after
modelBuilder.Entity<OrderSnapshot>().ToTable("Order").HasKey(s => s.SnapshotId).HasName("PK_Order_Snapshot");
Defensive patterns

Strategy: validation

Validate before calling

// Detect key-name collisions with differing columns on the same table.
var groups = modelBuilder.Model.GetEntityTypes()
    .SelectMany(e => e.GetDeclaredKeys())
    .GroupBy(k => new { Name = k.GetName(), Table = k.DeclaringEntityType.GetSchemaQualifiedTableName() })
    .Where(g => g.Count() > 1);
foreach (var g in groups)
{
    var cols = g.Select(k => string.Join(",", k.Properties.Select(p => p.GetColumnName()))).Distinct();
    if (cols.Count() > 1)
        Console.WriteLine($"Key '{g.Key.Name}' on '{g.Key.Table}' has conflicting columns.");
}

Prevention

When it happens

Trigger: RelationalKeyExtensions.AreCompatible with shouldThrow:true when !columnNames.SequenceEqual(duplicateColumnNames). Triggered when two entities on the same table each define a key whose properties resolve to different columns under a shared constraint name.

Common situations: Table-splitting where the owner defines a PK and a partner entity defines an alternate key with a colliding name; explicit HasName copy/paste errors across different properties.

Related errors


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

Appendix: source

Thrown at src/EFCore.Relational/Metadata/Internal/RelationalKeyExtensions.cs:45

    {
        var columnNames = key.Properties.GetColumnNames(storeObject);
        var duplicateColumnNames = duplicateKey.Properties.GetColumnNames(storeObject);
        return columnNames == null
            || duplicateColumnNames == null
                ? shouldThrow
                    ? throw new InvalidOperationException(
                        RelationalStrings.DuplicateKeyTableMismatch(
                            key.Properties.Format(),
                            key.DeclaringEntityType.DisplayName(),
                            duplicateKey.Properties.Format(),
                            duplicateKey.DeclaringEntityType.DisplayName(),
                            key.GetName(storeObject),
                            key.DeclaringEntityType.GetSchemaQualifiedTableName(),
                            duplicateKey.DeclaringEntityType.GetSchemaQualifiedTableName()))
                    : false
                : columnNames.SequenceEqual(duplicateColumnNames)
                || (shouldThrow
                    ? throw new InvalidOperationException(
                        RelationalStrings.DuplicateKeyColumnMismatch(
                            key.Properties.Format(),
                            key.DeclaringEntityType.DisplayName(),
                            duplicateKey.Properties.Format(),
                            duplicateKey.DeclaringEntityType.DisplayName(),
                            key.DeclaringEntityType.GetSchemaQualifiedTableName(),
                            key.GetName(storeObject),
                            key.Properties.FormatColumns(storeObject),
                            duplicateKey.Properties.FormatColumns(storeObject)))
                    : 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>

View on GitHub (pinned to 3a2006ef56)