dotnet/efcore · error · InvalidOperationException

The table '{table}' cannot be used for entity type '{entityT

Error message

The table '{table}' cannot be used for entity type '{entityType}' since it is being used for entity type '{otherEntityType}' and potentially other entity types, but there is no linking relationship. Add a foreign key to '{entityType}' on the primary key properties and pointing to the primary key on another entity type mapped to '{table}'.

What it means

When two or more entity types are mapped to the same table, EF requires them to be connected either by inheritance or by an identifying foreign key (a FK on the dependent's primary key pointing at the principal's PK). The validator at line 1184-1191 throws when it encounters a second 'root' (an entity type with no connecting relationship to the first root) sharing the table — EF cannot decide which type owns the row.

Source

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

                    .FirstOrDefault(fk => fk.PrincipalKey.IsPrimaryKey()
                        && !fk.PrincipalEntityType.IsAssignableFrom(fk.DeclaringEntityType)
                        && unvalidatedTypes.Contains(fk.PrincipalEntityType)) is { } linkingFK))
            {
                if (mappedType.BaseType != null)
                {
                    throw new InvalidOperationException(
                        RelationalStrings.IncompatibleTableDerivedRelationship(
                            table.DisplayName(),
                            mappedType.DisplayName(),
                            linkingFK.PrincipalEntityType.DisplayName()));
                }

                continue;
            }

            if (root != null)
            {
                throw new InvalidOperationException(
                    RelationalStrings.IncompatibleTableNoRelationship(
                        table.DisplayName(),
                        mappedType.DisplayName(),
                        root.DisplayName()));
            }

            root = mappedType;
        }

        Check.DebugAssert(root != null);
        unvalidatedTypes.Remove(root);
        var typesToValidate = new Queue<IEntityType>();
        typesToValidate.Enqueue(root);

        while (typesToValidate.Count > 0)
        {
            var entityType = typesToValidate.Dequeue();
            var key = entityType.FindPrimaryKey();

View on GitHub (pinned to dbf9771522)

Solutions

  1. Add a foreign key on the dependent entity's primary key properties pointing to the principal's primary key: .HasOne(...).HasForeignKey(...).
  2. If the two types are meant to be one row, model one as owned by the other (.OwnsOne) so EF creates the implicit FK.
  3. If they are genuinely unrelated, map them to different tables.

Example fix

// before
modelBuilder.Entity<Order>().ToTable("Records");
modelBuilder.Entity<OrderAudit>().ToTable("Records"); // no FK

// after
modelBuilder.Entity<OrderAudit>()
    .HasOne<Order>()
    .WithOne()
    .HasForeignKey<OrderAudit>(a => a.Id);
modelBuilder.Entity<Order>().ToTable("Records");
modelBuilder.Entity<OrderAudit>().ToTable("Records");
Defensive patterns

Strategy: validation

Validate before calling

var byTable = modelBuilder.Model.GetEntityTypes()
    .Where(e => !e.IsMappedToJson())
    .GroupBy(e => (e.GetTableName(), e.GetSchema()))
    .Where(g => g.Count() > 1);
foreach (var grp in byTable)
{
    var types = grp.ToList();
    for (int i = 1; i < types.Count; i++)
    {
        bool connected = types[i].BaseType != null && types.Contains(types[i].BaseType)
            || HasLinkingFk(types[i], types[0])
            || HasLinkingFk(types[0], types[i]);
        if (!connected)
            throw new InvalidOperationException(
                $"Types {types[0].Name} and {types[i].Name} share table without a linking FK.");
    }
}
bool HasLinkingFk(IEntityType dep, IEntityType prin)
    => dep.FindPrimaryKey() is { } pk
       && dep.FindForeignKeys(pk.Properties).Any(fk =>
            fk.PrincipalKey.IsPrimaryKey()
            && fk.PrincipalEntityType == prin
            && !fk.PrincipalEntityType.IsAssignableFrom(dep));

Prevention

When it happens

Trigger: Calling `.ToTable("SameTable")` on two unrelated entity types without defining a foreign key between their primary keys. Detected at the initial root-finding loop (line 1156-1194) when `root` is already set and a new unconnected type is found.

Common situations: Manually co-locating two entities in one table for performance without setting up the relationship; renaming a table to collide with another entity's table; CUD stored procedure or view scenarios where sharing was intended but the FK was forgotten.

Related errors


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