dotnet/efcore · error · InvalidOperationException
Entity type '{entityType}' has a split mapping for '{storeOb
Error message
Entity type '{entityType}' has a split mapping for '{storeObject}', but it also participates in an entity type hierarchy. Split mappings are not supported for hierarchies. What it means
ValidateMappingFragment refuses entity splitting (.SplitToTable / EntityTypeMappingFragment) for any entity that participates in an inheritance hierarchy, whether it has a BaseType or has directly derived types. Splitting fragments across a hierarchy is unsupported because EF cannot reconcile per-fragment row-internal FKs with inheritance mapping, so it throws on the first fragment.
Source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:2378
/// <summary>
/// Validates the mapping fragments for an entity type.
/// </summary>
/// <param name="entityType">The entity type to validate.</param>
/// <param name="logger">The logger to use.</param>
protected virtual void ValidateMappingFragment(
IEntityType entityType,
IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
{
var fragments = EntityTypeMappingFragment.Get(entityType);
if (fragments == null)
{
return;
}
if (entityType.BaseType != null
|| entityType.GetDirectlyDerivedTypes().Any())
{
throw new InvalidOperationException(
RelationalStrings.EntitySplittingHierarchy(entityType.DisplayName(), fragments.First().StoreObject.DisplayName()));
}
var anyTableFragments = false;
var anyViewFragments = false;
foreach (var fragment in fragments)
{
var mainStoreObject = StoreObjectIdentifier.Create(entityType, fragment.StoreObject.StoreObjectType);
if (mainStoreObject == null)
{
throw new InvalidOperationException(
RelationalStrings.EntitySplittingUnmappedMainFragment(
entityType.DisplayName(), fragment.StoreObject.DisplayName(), fragment.StoreObject.StoreObjectType));
}
if (fragment.StoreObject == mainStoreObject)
{
throw new InvalidOperationException(View on GitHub (pinned to dbf9771522)
Solutions
- Remove .SplitToTable calls from any entity that has a base or derived type; keep all its properties in the main table.
- If you need horizontal decomposition, model it as owned types or one-to-one relationships instead of entity splitting.
- Pull the split entity out of the hierarchy (remove HasBaseType) so splitting becomes legal.
Example fix
// before
modelBuilder.Entity<Customer>().HasBaseType<Person>()
.SplitToTable("CustomerExtras", t => t.Property(c => c.Notes));
// after
modelBuilder.Entity<Customer>().HasBaseType<Person>();
// move Notes into an owned type or a separate 1:1 entity instead of a split fragment Defensive patterns
Strategy: validation
Validate before calling
bool NoSplittingInHierarchies(DbContext context)
{
foreach (var et in context.Model.GetEntityTypes())
{
if (!et.GetTableMappingFragments().Any() && !et.GetViewMappingFragments().Any()) continue;
if (et.BaseType != null || et.GetDirectlyDerivedTypes().Any()) return false;
}
return true;
} Try / catch
try { _ = context.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("split mapping", StringComparison.Ordinal) && ex.Message.Contains("hierarchy", StringComparison.Ordinal))
{
throw new InvalidOperationException("Entity splitting is not supported inside an inheritance hierarchy. Remove .SplitToTable or use owned types instead.", ex);
} Prevention
- Never call .SplitToTable on a base or derived entity type.
- Prefer owned types or 1:1 entities for horizontal decomposition within hierarchies.
- Add a model test asserting no hierarchy member has mapping fragments.
When it happens
Trigger: An entity type has at least one EntityTypeMappingFragment (created by .SplitToTable(...)) AND (entityType.BaseType != null OR entityType.GetDirectlyDerivedTypes().Any()). Reported with the first fragment's store object name.
Common situations: Applying entity splitting (a common optimization for wide tables) to a base or derived entity that is later added to an inheritance chain; scaffolding splits then introducing a hierarchy; refactoring a flat entity into a base class while keeping its SplitToTable calls.
Related errors
- The short name for '{entityType1}' is '{discriminatorValue}'
- The mapping strategy '{mappingStrategy}' specified on '{enti
- 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/24e92b3cf840fc42.
Report an issue: GitHub.