dotnet/efcore · error · InvalidOperationException

Entity type ' ' has a split mapping, but it doesn't map any…

Error message

Entity type '{entityType}' has a split mapping, but it doesn't map any non-primary key property to the main store object. Keep at least one non-primary key property mapped to a column on '{storeObject}'.

What it means

ValidateMainMapping walks the MAIN store object (the entity's primary table/view). It requires at least one non-key property still mapped there (propertyFound). If every non-key property has been moved onto split fragments so the main object holds only the key, the mapping is rejected — entity splitting must leave payload on the main table.

Solutions

  1. Keep at least one non-key property mapped to the main store object (do not null-out all payload columns on the default table).
  2. Audit table-specific overrides on the default ToTable to confirm none of them strip every payload column.
  3. If the intent really is a key-only root, redesign with owned types or a separate entity instead of splitting.

Example fix

// before — every payload column unmapped on main table
modelBuilder.Entity<Invoice>()
    .ToTable("Invoice", tb =>
    {
        tb.Property(i => i.Amount).HasColumnName(null);
        tb.Property(i => i.Note).HasColumnName(null);
    })
    .SplitToTable("InvoiceDetail", tb =>
    {
        tb.Property(i => i.Id).HasColumnName("Id");
        tb.Property(i => i.Amount).HasColumnName("Amount");
        tb.Property(i => i.Note).HasColumnName("Note");
    }); // main has only Id -> [442]

// after — keep a payload column on the main table
modelBuilder.Entity<Invoice>()
    .ToTable("Invoice", tb => tb.Property(i => i.Amount).HasColumnName("Amount"))
    .SplitToTable("InvoiceDetail", tb =>
    {
        tb.Property(i => i.Id).HasColumnName("Id");
        tb.Property(i => i.Note).HasColumnName("Note");
    });
Defensive patterns

Strategy: validation

Validate before calling

// Verify the main store object keeps at least one non-key property.
static bool MainHasPayload(IEntityType et, StoreObjectIdentifier main)
    => et.GetProperties().Any(p => !p.IsPrimaryKey() && p.GetColumnName(main) is not null);

Prevention

When it happens

Trigger: Splitting an entity and unmapping every non-PK property from the main table (e.g. .HasColumnName(null) on the default table for all payload properties while mapping them only to SplitToTable fragments), so propertyFound stays false inside ValidateMainMapping.

Common situations: Over-aggressive splitting; treating the main table as a pure key/join table; bugs in code-generated mapping where the main ToTable loses its columns.

Related errors


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

Appendix: source

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

                }

                var columnName = property.GetColumnName(mainObject);
                if (columnName != null)
                {
                    propertyFound = true;

                    if (!nonSharedRequiredPropertyFound
                        && !property.IsNullable
                        && property.FindSharedStoreObjectRootProperty(mainObject) == null)
                    {
                        nonSharedRequiredPropertyFound = true;
                    }
                }
            }

            if (!propertyFound)
            {
                throw new InvalidOperationException(
                    RelationalStrings.EntitySplittingMissingPropertiesMainFragment(
                        entityType.DisplayName(), mainObject.DisplayName()));
            }

            if (!nonSharedRequiredPropertyFound)
            {
                var rowInternalFk = entityType.FindRowInternalForeignKeys(mainObject).First(fk => !fk.IsRequiredDependent);
                throw new InvalidOperationException(
                    RelationalStrings.EntitySplittingMissingRequiredPropertiesOptionalDependent(
                        entityType.DisplayName(), mainObject.DisplayName(),
                        $".Navigation(p => p.{rowInternalFk.PrincipalToDependent!.Name}).IsRequired()"));
            }

            return mainObject;
        }
    }

    /// <summary>

View on GitHub (pinned to 3a2006ef56)