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 map any non-primary key property to it. Map at least one non-primary key property to a column on '{storeObject}'.

What it means

A split fragment must carry at least one NON-primary-key property; otherwise it adds a redundant store object with no real data. ValidateMappingFragment tracks propertiesFound while iterating properties and throws EntitySplittingMissingProperties if no non-PK property resolves to a column on the fragment.

Source

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

                    if (property.IsPrimaryKey())
                    {
                        throw new InvalidOperationException(
                            RelationalStrings.EntitySplittingMissingPrimaryKey(
                                entityType.DisplayName(), fragment.StoreObject.DisplayName()));
                    }

                    continue;
                }

                if (!property.IsPrimaryKey())
                {
                    propertiesFound = true;
                }
            }

            if (!propertiesFound)
            {
                throw new InvalidOperationException(
                    RelationalStrings.EntitySplittingMissingProperties(
                        entityType.DisplayName(), fragment.StoreObject.DisplayName()));
            }

            switch (fragment.StoreObject.StoreObjectType)
            {
                case StoreObjectType.Table:
                    anyTableFragments = true;
                    break;
                case StoreObjectType.View:
                    anyViewFragments = true;
                    break;
            }
        }

        if (anyTableFragments)
        {
            ValidateMainMapping(entityType, StoreObjectIdentifier.Create(entityType, StoreObjectType.Table)!.Value);

View on GitHub (pinned to dbf9771522)

Solutions

  1. Move at least one non-key property onto the fragment: t.Property(c => c.LargeColumn).
  2. Remove the empty fragment entirely if it no longer holds any payload.
  3. If you only need the key, the split fragment serves no purpose - merge it back into the main table.

Example fix

// before
modelBuilder.Entity<Customer>().ToTable("Customers")
    .SplitToTable("CustomerExtras", t =>
    {
        t.Property(c => c.Id).HasColumnName("CustomerId"); // only the key
    });

// after
modelBuilder.Entity<Customer>().ToTable("Customers")
    .SplitToTable("CustomerExtras", t =>
    {
        t.Property(c => c.Id).HasColumnName("CustomerId");
        t.Property(c => c.Biography); // a non-key payload
    });
Defensive patterns

Strategy: validation

Validate before calling

bool SplitFragmentsHavePayload(DbContext context)
{
    foreach (var et in context.Model.GetEntityTypes())
    foreach (var f in et.GetTableMappingFragments())
    {
        bool any = et.GetProperties().Any(p => !p.IsPrimaryKey() && p.GetColumnName(f.StoreObject) is not null);
        if (!any) return false;
    }
    return true;
}

Try / catch

try { _ = context.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("split mapping", StringComparison.Ordinal) && ex.Message.Contains("non-primary key", StringComparison.Ordinal) && !ex.Message.Contains("main store object", StringComparison.Ordinal))
{
    throw new InvalidOperationException("A split fragment has no non-key property. Move at least one payload column onto it or remove the fragment.", ex);
}

Prevention

When it happens

Trigger: A .SplitToTable fragment only maps primary key columns (or maps nothing but the key). The loop sets propertiesFound only for non-PK properties with a column; if none are found, it throws.

Common situations: Adding a split fragment then moving all its non-key properties elsewhere or ignoring them; scaffolding splits that ended up empty after manual trimming; refactoring that left a fragment with only the join key.

Related errors


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