dotnet/efcore · error · InvalidOperationException

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

Error message

The keys {keyProperties1} on '{entityType1}' and {keyProperties2} on '{entityType2}' are both mapped to '{keyName}', but on different tables ('{table1}' and '{table2}').

What it means

Two keys share the same database name but their declaring entities are mapped to different tables, so at least one cannot produce a column list for the store object. One key constraint name cannot span two tables.

Solutions

  1. Give each key a distinct name via HasName(...) on the key.
  2. Ensure both keys are mapped to the same table if the shared name is intentional.
  3. Remove the redundant key definition.
  4. When changing inheritance strategy, regenerate constraint names.

Example fix

// before: TPT, both default to 'PK_Base'
modelBuilder.Entity<Base>().ToTable("Base").HasKey(b => b.Id);
modelBuilder.Entity<Derived>().ToTable("Derived").HasKey(d => d.Id);

// after: rename one
modelBuilder.Entity<Derived>().ToTable("Derived").HasKey(d => d.Id).HasName("PK_Derived");
Defensive patterns

Strategy: validation

Validate before calling

// Find keys whose names collide across different tables.
var keys = modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetDeclaredKeys());
foreach (var k in keys)
{
    var name = k.GetName();
    foreach (var dup in keys.Where(o => o != k && o.GetName() == name
                                       && o.DeclaringEntityType.GetSchemaQualifiedTableName() != k.DeclaringEntityType.GetSchemaQualifiedTableName()))
    {
        Console.WriteLine($"Key name '{name}' used on two tables: {k.DeclaringEntityType.Name} and {dup.DeclaringEntityType.Name}.");
    }
}

Prevention

When it happens

Trigger: RelationalKeyExtensions.AreCompatible with shouldThrow:true when key.Properties.GetColumnNames(storeObject) or duplicateKey.Properties.GetColumnNames(storeObject) returns null. Common in TPT/Tpc inheritance where the same key constraint name is reused across the base and derived tables.

Common situations: TPT hierarchies with default key naming; explicit HasKeyName reuse across entities mapped to different tables; switching mapping strategies without renaming constraints.

Related errors


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

Appendix: source

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

{
    /// <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 bool AreCompatible(
        this IReadOnlyKey key,
        IReadOnlyKey duplicateKey,
        in StoreObjectIdentifier storeObject,
        bool shouldThrow)
    {
        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(),

View on GitHub (pinned to 3a2006ef56)