dotnet/efcore · error · InvalidOperationException
Entity type ' ' has a split mapping for ' ', but the…
Error message
Entity type '{entityType}' has a split mapping for '{storeObject}', but the primary key properties aren't fully mapped. Map all primary key properties to columns on '{storeObject}'. What it means
Entity splitting spreads one entity across several tables via SplitToTable/SplitToView fragments. The relational model validator walks each fragment and resolves a column name for every property; if a PRIMARY KEY property resolves to no column on a fragment, it throws, because the fragment cannot link its rows back to the entity without the full key. All key columns must be present on every split fragment.
Solutions
- Ensure every primary key property has a column on the offending fragment: property.HasColumnName("Id", "ExtraFragmentName").
- Remove any table-specific override (.HasColumnName(null, fragment)) that is suppressing a key column on the fragment.
- If the fragment cannot carry the full key, drop the fragment and model the extra columns differently (owned type, one-to-one, or TPH).
- Verify the entity's key is not shadow/composite-with-unmapped-part that never reaches the fragment.
Example fix
// before
modelBuilder.Entity<Customer>()
.SplitToTable("CustomerExtra", tb =>
{
tb.Property(c => c.Notes).HasColumnName("Notes");
// Id not mapped -> [440]
});
// after
modelBuilder.Entity<Customer>()
.SplitToTable("CustomerExtra", tb =>
{
tb.Property(c => c.Id).HasColumnName("Id");
tb.Property(c => c.Notes).HasColumnName("Notes");
}); Defensive patterns
Strategy: validation
Validate before calling
// Before relying on the model, verify every key property has a column on each split fragment.
foreach (var fragment in entityType.GetTableMappings().SelectMany(t => t.EntityTypeMappings).SelectMany(m => m.TableMappings is null ? Array.Empty<object>() : Array.Empty<object>())) { /* placeholder */ }
// Simpler: assert key coverage per fragment store object.
var fragments = entityType.GetFragmentMappings(); // or your mapping accessor
foreach (var fragment in entityType.GetMappingFragments())
{
foreach (var keyProp in entityType.FindPrimaryKey()!.Properties)
{
if (keyProp.GetColumnName(fragment.StoreObject) is null)
throw new InvalidOperationException($"Key property {keyProp.Name} is unmapped on fragment {fragment.StoreObject.DisplayName()}.");
}
} Type guard
// Guard before adding a split fragment.
static bool IsKeyFullyMappedOnFragment(IEntityType et, StoreObjectIdentifier store)
=> et.FindPrimaryKey()!.Properties.All(p => p.GetColumnName(store) is not null); Prevention
- Centralize split-mapping setup in one place and assert key coverage per fragment after configuration.
- Never null-out a key column with .HasColumnName(null, fragment).
- Write a model-snapshot test that builds the model and exercises the validator to catch this at test time.
When it happens
Trigger: Calling entityTypeBuilder.SplitToTable("Extra") (or SplitToView / a MappingFragment) and then unmapping or renaming a key property on that fragment, e.g. property.HasColumnName(null, "Extra") on an Id property, or a table-specific override that drops the key column. Also triggered when a key convention is suppressed so GetColumnName(fragment.StoreObject) returns null for a key property.
Common situations: Copying a SplitToTable block and forgetting to map the key; using table-specific column overrides (.HasColumnName(name, name: "Extra")) that accidentally exclude the PK; renaming fragments; upgrading EF and a previously-tolerated mapping now fails validation.
Related errors
- Entity type ' ' has a split mapping, but it doesn't map any…
- Entity type ' ' has a split mapping for ' ', but it doesn't…
- The keyless entity type
- Both entity type ' ' and ' ' were configured to use ' '…
- Current value parameter
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/bd285f933f93c72d.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:2424
{
throw new InvalidOperationException(
RelationalStrings.EntitySplittingUnmatchedMainTableSplitting(
entityType.DisplayName(),
fragment.StoreObject.DisplayName(),
foreignKey.PrincipalEntityType.DisplayName(),
principalMainFragment.DisplayName()));
}
}
var propertiesFound = false;
foreach (var property in entityType.GetProperties())
{
var columnName = property.GetColumnName(fragment.StoreObject);
if (columnName == null)
{
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()));View on GitHub (pinned to 3a2006ef56)