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 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

Thrown when the validator processes entity types sharing a table, finds an entity type with no linking FK to the others and no established root, and rejects the unlinked share. The message lists the table, the unlinked entity type, and the root (the first entity type that claimed the table). Each subsequent sharing type must either be in the same inheritance hierarchy or have a PK→PK FK to a sibling.

Solutions

  1. Add a one-to-one FK on the dependent entity's primary key pointing to the principal's primary key: builder.Entity<Customer>().HasOne(c => c.Order).WithOne(o => o.Customer).HasForeignKey<Order>(o => o.Id).
  2. If the entities are conceptually one type, consolidate them into a single entity or use inheritance with the base mapped to the same table.
  3. Map one of them to a different table.

Example fix

// before
builder.Entity<Customer>().ToTable("Users");
builder.Entity<Order>().ToTable("Users"); // unrelated -> error

// after
builder.Entity<Customer>().ToTable("Users");
builder.Entity<Order>(b =>
{
    b.ToTable("Users");
    b.HasOne(o => o.Customer).WithOne(c => c.Order)
        .HasForeignKey<Order>(o => o.CustomerId);
});
Defensive patterns

Strategy: validation

Validate before calling

// Group entity types by table and flag shares without inheritance or PK FK link.
var byTable = model.GetEntityTypes().Where(e => e.GetTableName() != null).GroupBy(e => e.GetTableName());
foreach (var grp in byTable)
{
    var list = grp.ToList();
    for (int i = 1; i < list.Count; i++)
    {
        bool linked = list[i].BaseType != null && list.Any(t => t.IsAssignableFrom(list[i]))
            || list[i].FindForeignKeys(list[i].FindPrimaryKey()?.Properties ?? new List<Microsoft.EntityFrameworkCore.Metadata.IProperty>())
                .Any(fk => fk.PrincipalEntityType == list[0] && fk.PrincipalKey.IsPrimaryKey());
        if (!linked)
            Console.WriteLine($"{list[i].Name} shares table '{grp.Key}' with {list[0].Name} but has no link.");
    }
}

Prevention

When it happens

Trigger: Two or more unrelated entity types mapped to the same table without an inheritance relationship or a one-to-one FK on their primary keys. E.g. [Table("Users")] on both Customer and Order without Customer.OrderId FK on the PK.

Common situations: Accidentally setting ToTable("X") on two unrelated entities; renaming a table to collide; converting an entity to owned without using OwnsOne; missing HasForeignKey configuration on a 1:1 sharing.

Related errors


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

Appendix: 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 3a2006ef56)