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 doesn't have a main mapping of the same type. Map '{entityType}' to '{storeObjectType}'.

What it means

ValidateMappingFragment requires that for every split fragment, the entity has a MAIN mapping of the same store object type. If you call .SplitToTable("Extras", ...) but the entity is not itself mapped to a table (StoreObjectIdentifier.Create(entity, Table) returns null), EF has nothing to split FROM and throws, naming the fragment and the missing store object type.

Source

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

        {
            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(
                    RelationalStrings.EntitySplittingConflictingMainFragment(
                        entityType.DisplayName(), fragment.StoreObject.DisplayName()));
            }

            foreach (var foreignKey in entityType.FindRowInternalForeignKeys(fragment.StoreObject))
            {
                var principalMainFragment = StoreObjectIdentifier.Create(
                    foreignKey.PrincipalEntityType, fragment.StoreObject.StoreObjectType)!.Value;
                if (principalMainFragment != mainStoreObject)
                {
                    throw new InvalidOperationException(

View on GitHub (pinned to dbf9771522)

Solutions

  1. Add the matching main mapping: modelBuilder.Entity<E>().ToTable("E") before .SplitToTable(...).
  2. If splitting a view, also map the main object as a view via .ToView("main").
  3. Remove the split fragment whose store object type has no corresponding main mapping.

Example fix

// before
modelBuilder.Entity<Customer>().ToView("v_Customer")
    .SplitToTable("CustomerExtras", t => t.Property(c => c.Notes)); // no main table

// after
modelBuilder.Entity<Customer>().ToTable("Customers")
    .SplitToTable("CustomerExtras", t => t.Property(c => c.Notes));
Defensive patterns

Strategy: validation

Validate before calling

bool SplitFragmentsHaveMainMapping(DbContext context)
{
    foreach (var et in context.Model.GetEntityTypes())
    {
        foreach (var f in et.GetTableMappingFragments())
            if (StoreObjectIdentifier.Create(et, StoreObjectType.Table) is null) return false;
        foreach (var f in et.GetViewMappingFragments())
            if (StoreObjectIdentifier.Create(et, StoreObjectType.View) is null) return false;
    }
    return true;
}

Try / catch

try { _ = context.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("split mapping", StringComparison.Ordinal) && ex.Message.Contains("main mapping", StringComparison.Ordinal))
{
    throw new InvalidOperationException("A split fragment needs a main mapping of the same store object type. Add ToTable/ToView to the entity.", ex);
}

Prevention

When it happens

Trigger: An EntityTypeMappingFragment exists for StoreObjectType.Table (or View), but StoreObjectIdentifier.Create(entityType, fragment.StoreObject.StoreObjectType) is null because the entity was mapped ToView-only (or not at all) while split fragments targeted tables, or vice versa for views.

Common situations: Calling .SplitToTable on an entity that is query-only via .ToView and has no table; mixing .ToView with .SplitToTable without an explicit ToTable; scaffolding splits for a view-mapped entity.

Related errors


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