dotnet/efcore · error · InvalidOperationException

The table ' ' cannot be used for entity type ' ' since it…

Error message

The table '{table}' cannot be used for entity type '{entityType}' since it is being used for entity type '{otherEntityType}' and the name '{keyName}' of the primary key {primaryKey} does not match the name '{otherName}' of the primary key {otherPrimaryKey}.

What it means

Thrown when entity types sharing a table have different primary-key names for that table (computed via key.GetName(table)). The validator ensures every sharing type agrees on the PK constraint name; a mismatch would produce conflicting DDL/migration. Names are compared with key.GetName(table) for each connected entity type.

Solutions

  1. Unify the PK constraint name across all entity types sharing the table: .HasKey(e => e.Id).HasName("PK_Users") on every sharing entity (or remove all explicit HasName so they fall back to the same convention).
  2. If the names truly must differ, the types must not share a table — remap one of them.
  3. Generate/check a migration to confirm the resulting PK constraint name.

Example fix

// before
builder.Entity<Customer>().HasKey(c => c.Id).HasName("PK_Customers");
builder.Entity<Customer>().ToTable("Users");
builder.Entity<User>().ToTable("Users"); // default PK name

// after
builder.Entity<Customer>().HasKey(c => c.Id).HasName("PK_Users");
builder.Entity<User>().HasKey(u => u.Id).HasName("PK_Users");
Defensive patterns

Strategy: validation

Validate before calling

var byTable = model.GetEntityTypes().Where(e => e.GetTableName() != null).GroupBy(e => e.GetTableName());
foreach (var grp in byTable)
{
    var names = grp.Select(e => (e, e.FindPrimaryKey()?.GetName(StoreObjectIdentifier.Table(grp.Key)))).ToList();
    var distinct = names.Where(n => n.Item2 != null).Select(n => n.Item2).Distinct().ToList();
    if (distinct.Count > 1)
        Console.WriteLine($"Table '{grp.Key}' has multiple PK names: {string.Join(", ", distinct)}");
}

Prevention

When it happens

Trigger: Two entity types mapped to the same table where one has been given a custom PK name via .HasKey(...).HasName("PK_Foo") (or via HasPrincipalKey name on the relationship) and the other uses a different name. Often emerges in TPH/TPT where conventions assign names differently, or when migrations add explicit names.

Common situations: Hand-named PK constraints on one entity but not the other; merging two contexts that share a table; explicit constraint names from a migration that did not propagate to siblings.

Related errors


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

Appendix: source

Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:1219

        while (typesToValidate.Count > 0)
        {
            var entityType = typesToValidate.Dequeue();
            var key = entityType.FindPrimaryKey();
            var comment = entityType.GetComment();
            var isExcluded = entityType.IsTableExcludedFromMigrations(table);
            var typesToValidateLeft = typesToValidate.Count;
            var directlyConnectedTypes = unvalidatedTypes.Where(unvalidatedType =>
                entityType.IsAssignableFrom(unvalidatedType)
                || IsIdentifyingPrincipal(unvalidatedType, entityType));

            foreach (var nextEntityType in directlyConnectedTypes)
            {
                if (key != null)
                {
                    var otherKey = nextEntityType.FindPrimaryKey()!;
                    if (key.GetName(table) != otherKey.GetName(table))
                    {
                        throw new InvalidOperationException(
                            RelationalStrings.IncompatibleTableKeyNameMismatch(
                                table.DisplayName(),
                                entityType.DisplayName(),
                                nextEntityType.DisplayName(),
                                key.GetName(table),
                                key.Properties.Format(),
                                otherKey.GetName(table),
                                otherKey.Properties.Format()));
                    }
                }

                var nextComment = nextEntityType.GetComment();
                if (comment != null)
                {
                    if (nextComment != null
                        && !comment.Equals(nextComment, StringComparison.Ordinal))
                    {
                        throw new InvalidOperationException(

View on GitHub (pinned to 3a2006ef56)