dotnet/efcore · error · InvalidOperationException
The entity type '{dependentType}' is mapped to '{storeObject
Error message
The entity type '{dependentType}' is mapped to '{storeObject}'. However one of its derived types '{derivedType}' is mapped to '{otherStoreObject}'. Hierarchies using table-sharing cannot be mapped using the TPC mapping strategy. What it means
Also in ValidateNonTphMapping for TPC: if the root entity has row-internal foreign keys (i.e. table-sharing) and more than one entity type in the hierarchy is mapped, the model is rejected because TPC requires each concrete type in its own table and cannot represent a shared root table across a hierarchy. The first non-root derived mapping is reported.
Source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:2286
rowInternalFk.PrincipalEntityType.DisplayName()));
}
}
derivedTypes[storeObject.Value] = entityType;
}
var rootStoreObject = StoreObjectIdentifier.Create(rootEntityType, storeObjectType);
if (rootStoreObject == null)
{
return;
}
if (rootEntityType.FindRowInternalForeignKeys(rootStoreObject.Value).Any()
&& derivedTypes.Count > 1
&& rootEntityType.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy)
{
var derivedTypePair = derivedTypes.First(kv => kv.Value != rootEntityType);
throw new InvalidOperationException(
RelationalStrings.TpcTableSharingDependent(
rootEntityType.DisplayName(),
rootStoreObject.Value.DisplayName(),
derivedTypePair.Value.DisplayName(),
derivedTypePair.Key.DisplayName()));
}
}
private static void ValidateTphMapping(IEntityType rootEntityType, StoreObjectType storeObjectType)
{
var isSproc = storeObjectType is StoreObjectType.DeleteStoredProcedure
or StoreObjectType.InsertStoredProcedure
or StoreObjectType.UpdateStoredProcedure;
var rootSproc = isSproc ? StoredProcedure.FindDeclaredStoredProcedure(rootEntityType, storeObjectType) : null;
var rootId = StoreObjectIdentifier.Create(rootEntityType, storeObjectType);
foreach (var entityType in rootEntityType.GetDerivedTypes())
{
var entityId = StoreObjectIdentifier.Create(entityType, storeObjectType);View on GitHub (pinned to dbf9771522)
Solutions
- Break the table sharing on the root so FindRowInternalForeignKeys is empty: give the root (and any shared principal) distinct tables.
- Switch the hierarchy to TPT or TPH which can coexist with shared root tables.
- Collapse the hierarchy so there is only one mapped type (no derived mappings).
Example fix
// before
modelBuilder.Entity<Customer>().UseTpcMappingStrategy().ToTable("Contacts"); // Contacts shared
// after
modelBuilder.Entity<Customer>().UseTpcMappingStrategy().ToTable("Customers"); // exclusive table Defensive patterns
Strategy: validation
Validate before calling
bool TpcRootNotTableSharedWithHierarchy(DbContext context)
{
foreach (var root in context.Model.GetEntityTypes()
.Where(e => e.BaseType == null && e.GetMappingStrategy() == "TPC"))
{
var so = StoreObjectIdentifier.Create(root, StoreObjectType.Table);
if (so is null) continue;
bool shares = root.FindRowInternalForeignKeys(so.Value).Any();
int mappedCount = root.GetDerivedTypesInclusive().Count(d => StoreObjectIdentifier.Create(d, StoreObjectType.Table) != null);
if (shares && mappedCount > 1) return false;
}
return true;
} Try / catch
try { _ = context.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("TPC", StringComparison.Ordinal) && ex.Message.Contains("table-sharing", StringComparison.Ordinal) && ex.Message.Contains("derived", StringComparison.Ordinal))
{
throw new InvalidOperationException("A TPC root shares its table while multiple derived types are mapped. Break the sharing or switch to TPT.", ex);
} Prevention
- Do not combine .UseTpcMappingStrategy() with table-shared roots.
- Reserve TPC for hierarchies where every type lives in its own dedicated table.
- Validate the model in a unit test before deploying.
When it happens
Trigger: Root entity has TPC strategy, FindRowInternalForeignKeys returns at least one row-internal FK on the root store object, and derivedTypes.Count > 1 (multiple hierarchy members mapped). Typically appears when the root table is shared with another entity but you still want TPC over its derived types.
Common situations: Adding .UseTpcMappingStrategy() to an entity that also participates in table sharing (e.g. owned/inline or joint table) with derived types; migrating a shared-table design to TPC.
Related errors
- The entity type '{dependentType}' is mapped to '{storeObject
- The short name for '{entityType1}' is '{discriminatorValue}'
- Both '{entityType}' and '{otherEntityType}' are mapped to th
- Both '{entityType}' and '{otherEntityType}' are mapped to th
- Both '{entityType}' and '{otherEntityType}' are mapped to th
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/8e81d5fafd7cb37e.
Report an issue: GitHub.