dotnet/efcore · error · InvalidOperationException

Entity type ' ' has a split mapping for ' ' that is shared…

Error message

Entity type '{entityType}' has a split mapping for '{storeObject}' that is shared with the entity type '{principalEntityType}', but the main mappings of these types do not share a table. Map the split fragments of '{entityType}' to non-shared tables or map the main fragment to '{principalStoreObject}'.

What it means

Thrown in the entity-splitting validator when a split fragment of an entity shares its table with a principal entity (via a row internal foreign key, i.e. table splitting between two entities), but the main mappings of those two entities do not themselves share a table. The split fragment's principal main store object (StoreObjectIdentifier.Create of the principal for the same store-object type) differs from the dependent's mainStoreObject, so the relationship is inconsistent.

Solutions

  1. Align the principal's main mapping to the dependent's main table so the split fragment is shared consistently: ToTable the principal to the same store object.
  2. Or map the dependent's split fragments to non-shared tables (remove the row-internal-FK sharing on that fragment).
  3. Make the ownership/table-splitting consistent across both the main and split mappings.

Example fix

// before
modelBuilder.Entity<Customer>().ToTable("Customers");
modelBuilder.Entity<Customer>()
    .OwnsOne(c => c.Audit, a => a.ToTable("Customers")) // shares via row IFK
    .SplitToTable("CustomerExtras", t => t.Property(c => c.Notes));
// but principal main table differs -> throws 439

// after - keep principal main table aligned
modelBuilder.Entity<Customer>().ToTable("Customers");
modelBuilder.Entity<Customer>().OwnsOne(c => c.Audit, a => a.ToTable("Customers"));
// do not split a fragment that shares a table unless main tables also share
Defensive patterns

Strategy: validation

Validate before calling

foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
    var fragments = EntityTypeMappingFragment.Get(entityType);
    if (fragments == null) continue;
    foreach (var fragment in fragments)
    {
        var main = StoreObjectIdentifier.Create(entityType, fragment.StoreObject.StoreObjectType);
        if (main == null) continue;
        foreach (var fk in entityType.FindRowInternalForeignKeys(fragment.StoreObject))
        {
            var principalMain = StoreObjectIdentifier.Create(fk.PrincipalEntityType, fragment.StoreObject.StoreObjectType);
            if (principalMain != null && principalMain.Value != main.Value)
                throw new InvalidOperationException($"{entityType.DisplayName()} split fragment {fragment.StoreObject.DisplayName()} shares a table with {fk.PrincipalEntityType.DisplayName()} but main mappings differ ({main.Value.DisplayName()} vs {principalMain.Value.DisplayName()}).");
        }
    }
}

Prevention

When it happens

Trigger: An entity Customer is table-split with AuditInfo (AuditInfo has a row internal FK to Customer on the split fragment), but AuditInfo's main ToTable points somewhere different than Customer's main table, so the principalMainFragment != mainStoreObject for the fragment.

Common situations: Mixing entity splitting (SplitToTable) with owned/table-split types whose main tables drift apart; refactor that changed a principal's main table without updating the dependent's split fragment; inconsistent ToTable across an ownership.

Related errors


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

Appendix: source

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

                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(
                        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(

View on GitHub (pinned to 3a2006ef56)