{"record":{"id":"a806de288a1a16b9","repo":"dotnet/efcore","slug":"entity-type-entitytype-has-a-split-mapping-and","errorCode":null,"errorMessage":"Entity type '{entityType}' has a split mapping and is an optional dependent sharing a store object, but it doesn't map any required non-shared property to the main store object. Keep at least one required non-shared property mapped to a column on '{storeObject}' or mark '{entityType}' as a required dependent by calling '{requiredDependentConfig}'.","messagePattern":"Entity type '(.+?)' has a split mapping and is an optional dependent sharing a store object, but it doesn't map any required non-shared property to the main store object\\. Keep at least one required non-shared property mapped to a column on '(.+?)' or mark '(.+?)' as a required dependent by calling '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs","lineNumber":2503,"sourceCode":"                        && !property.IsNullable\n                        && property.FindSharedStoreObjectRootProperty(mainObject) == null)\n                    {\n                        nonSharedRequiredPropertyFound = true;\n                    }\n                }\n            }\n\n            if (!propertyFound)\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.EntitySplittingMissingPropertiesMainFragment(\n                        entityType.DisplayName(), mainObject.DisplayName()));\n            }\n\n            if (!nonSharedRequiredPropertyFound)\n            {\n                var rowInternalFk = entityType.FindRowInternalForeignKeys(mainObject).First(fk => !fk.IsRequiredDependent);\n                throw new InvalidOperationException(\n                    RelationalStrings.EntitySplittingMissingRequiredPropertiesOptionalDependent(\n                        entityType.DisplayName(), mainObject.DisplayName(),\n                        $\".Navigation(p => p.{rowInternalFk.PrincipalToDependent!.Name}).IsRequired()\"));\n            }\n\n            return mainObject;\n        }\n    }\n\n    /// <summary>\n    ///     Validates a table-specific property override for a property.\n    /// </summary>\n    /// <param name=\"property\">The property to validate.</param>\n    /// <param name=\"propertyOverride\">The property override to validate.</param>\n    /// <param name=\"logger\">The logger to use.</param>\n    protected virtual void ValidatePropertyOverride(\n        IProperty property,\n        IReadOnlyRelationalPropertyOverrides propertyOverride,","sourceCodeStart":2485,"sourceCodeEnd":2521,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L2485-L2521","documentation":"Thrown during model validation when an entity type uses entity splitting (maps to multiple table fragments) and is also an optional dependent (its row-internal foreign key is not required). EF requires that at least one non-shared, non-nullable property be mapped to the main store object, so a row can be distinguished from 'all nulls'. Without it EF cannot determine whether the optional dependent row exists. The validator at RelationalModelValidator.cs:2466-2507 iterates all non-PK properties and checks IsNullable and FindSharedStoreObjectRootProperty against the main table.","triggerScenarios":"Called by ValidateMainMapping when entityType.GetMappingFragments() returns table or view fragments AND entityType.FindRowInternalForeignKeys(mainObject) contains an FK where IsRequiredDependent is false, AND no non-PK property satisfies (GetColumnName(mainObject) != null && !IsNullable && FindSharedStoreObjectRootProperty(mainObject) == null).","commonSituations":"Using owned entity types with entity splitting (SplitToTable) where all non-key properties on the main table are either nullable, shared (FK columns from the principal), or moved to a split fragment. Common when migrating from TPH/owned types to splitting and accidentally making all columns nullable.","solutions":["Make at least one non-shared property non-nullable and map it to the main table (configure it as required).","Call .Navigation(p => p.YourNavigation).IsRequired() on the owning entity to mark the dependent as required, so EF doesn't need the sentinel column.","Move the split fragment mapping so that at least one required property stays on the main table rather than on the split fragment.","Add a non-nullable discriminator or sentinel property to the main table."],"exampleFix":"// before: all properties on main table are nullable or shared\nmodelBuilder.Entity<Order>()\n    .OwnsOne(o => o.Details, db =>\n    {\n        db.ToTable(\"OrderDetailsSplit\");\n        db.Property(d => d.Notes).HasColumnName(\"DetailsNotes\"); // only nullable props remain on main\n    });\n\n// after: mark the owned navigation as required\nmodelBuilder.Entity<Order>()\n    .OwnsOne(o => o.Details, db =>\n    {\n        db.ToTable(\"OrderDetailsSplit\");\n    })\n    .Navigation(o => o.Details)\n    .IsRequired();","handlingStrategy":"validation","validationCode":"// Before finalizing the model, check that each split-mapped optional dependent has a required non-shared property on the main table.\nforeach (var entityType in modelBuilder.Model.GetEntityTypes())\n{\n    var fragments = entityType.GetMappingFragments(StoreObjectType.Table).ToList();\n    if (fragments.Count == 0) continue;\n    var mainObj = StoreObjectIdentifier.Create(entityType, StoreObjectType.Table).GetValueOrDefault();\n    var hasNonRequiredFk = entityType.FindRowInternalForeignKeys(mainObj).Any(fk => !fk.IsRequiredDependent);\n    if (!hasNonRequiredFk) continue;\n    var hasRequiredNonShared = entityType.GetProperties()\n        .Where(p => !p.IsPrimaryKey())\n        .Any(p => p.GetColumnName(mainObj) != null && !p.IsNullable\n                  && p.FindSharedStoreObjectRootProperty(mainObj) == null);\n    if (!hasRequiredNonShared)\n        Console.WriteLine($\"WARN: {entityType.DisplayName()} needs a required property on {mainObj.DisplayName()} or IsRequired() on its navigation.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When using entity splitting with owned types, always call .Navigation(...).IsRequired() or ensure at least one non-nullable non-FK property stays on the main table.","Review split fragment mappings to ensure the main table retains a sentinel column for optional dependents.","Run model validation early in unit tests with context.Model.FinalizeModel() to catch this before runtime."],"tags":["entity-splitting","optional-dependent","model-validation","owned-types"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}