{"record":{"id":"b9f36265e8d4ba2e","repo":"dotnet/efcore","slug":"entity-type-entitytype-is-an-optional-dependen","errorCode":null,"errorMessage":"Entity type '{entityType}' is an optional dependent using table sharing and containing other dependents without any required non shared property to identify whether the entity exists. If all nullable properties contain a 'null' value in database then an object instance won't be created in the query causing nested dependent's values to be lost. Add a required property to create instances with 'null' values for other properties or mark the incoming navigation as required to always create an instance.","messagePattern":"Entity type '(.+?)' is an optional dependent using table sharing and containing other dependents without any required non shared property to identify whether the entity exists\\. If all nullable properties contain a 'null' value in database then an object instance won't be created in the query causing nested dependent's values to be lost\\. Add a required property to create instances with 'null' values for other properties or mark the incoming navigation as required to always create an instance\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs","lineNumber":1102,"sourceCode":"                    continue;\n                }\n\n                var columnName = property.GetColumnName(tableIdentifier);\n                if (columnName != null)\n                {\n                    if (!principalColumns.Contains(columnName))\n                    {\n                        requiredNonSharedColumnFound = true;\n                        break;\n                    }\n                }\n            }\n\n            if (!requiredNonSharedColumnFound)\n            {\n                if (entityType.GetReferencingForeignKeys().Select(e => e.DeclaringEntityType).Any(t => mappedTypes.Contains(t)))\n                {\n                    throw new InvalidOperationException(\n                        RelationalStrings.OptionalDependentWithDependentWithoutIdentifyingProperty(entityType.DisplayName()));\n                }\n\n                logger.OptionalDependentWithoutIdentifyingPropertyWarning(entityType);\n            }\n        }\n\n        (List<IEntityType> EntityTypes, bool Optional) GetPrincipalEntityTypes(IEntityType entityType)\n        {\n            if (!principalEntityTypesMap.TryGetValue(entityType, out var tuple))\n            {\n                var list = new List<IEntityType>();\n                var optional = false;\n                foreach (var foreignKey in entityType.FindForeignKeys(entityType.FindPrimaryKey()!.Properties))\n                {\n                    var principalEntityType = foreignKey.PrincipalEntityType;\n                    if (foreignKey.PrincipalEntityType.IsAssignableFrom(foreignKey.DeclaringEntityType)\n                        || !mappedTypes.Contains(principalEntityType))","sourceCodeStart":1084,"sourceCodeEnd":1120,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L1084-L1120","documentation":"When an optional dependent shares a table with its principal (table splitting / owned types) and has no required non-shared column, EF cannot distinguish a row of all-NULL dependent columns from an absent dependent — it will materialize null and silently lose any nested dependents' data. The validator at line 1098-1104 escalates this from a warning to an error when the optional dependent itself has nested dependents mapped to the same table, because data loss is then guaranteed on round-trip.","triggerScenarios":"An owned entity configured as optional (`IsRequired(false)` on the ownership or nullable navigation) whose columns are all nullable/shared-with-principal, AND that owned entity contains further owned entities. The check at line 1100 confirms nested dependents exist before throwing.","commonSituations":"Owned types with optional ownership and no required discriminator/flag property; making a previously-required navigation optional; adding nested owned types to an optional owned entity.","solutions":["Add a required (non-nullable) property to the optional dependent that is not shared with the principal — e.g. a boolean 'Exists' flag or a required value — so EF can detect instance presence.","Make the ownership required (.OwnsOne(...).IsRequired() or required navigation) so an instance is always created.","Map the optional dependent to its own table instead of sharing, removing the ambiguity."],"exampleFix":"// before\nmodelBuilder.Entity<Order>(b =>\n{\n    b.OwnsOne(o => o.Details, d =>\n    {\n        d.OwnsOne(x => x.Nested); // optional, no required non-shared column\n    });\n});\n\n// after - add a required sentinel property\nmodelBuilder.Entity<Order>(b =>\n{\n    b.OwnsOne(o => o.Details, d =>\n    {\n        d.Property<bool>(\"Exists\").IsRequired();\n        d.OwnsOne(x => x.Nested);\n    });\n});","handlingStrategy":"validation","validationCode":"// For each optional dependent sharing a table that itself has dependents,\n// ensure a required non-shared column exists.\nforeach (var et in modelBuilder.Model.GetEntityTypes())\n{\n    var ownership = et.FindOwnership();\n    if (ownership == null || ownership.IsRequired) continue;\n    var principal = ownership.PrincipalEntityType;\n    var table = et.GetTableName();\n    if (table == null) continue;\n\n    bool hasNestedDependent = et.GetReferencingForeignKeys()\n        .Any(rfk => rfk.DeclaringEntityType.GetTableName() == table);\n    if (!hasNestedDependent) continue;\n\n    var principalCols = principal.GetProperties()\n        .Select(p => p.GetColumnName(StoreObjectIdentifier.Table(table, et.GetSchema())))\n        .Where(n => n != null).ToHashSet();\n\n    bool hasRequiredNonShared = et.GetProperties().Any(p =>\n        !p.IsPrimaryKey() && !p.IsNullable\n        && p.GetColumnName(StoreObjectIdentifier.Table(table, et.GetSchema())) is string col\n        && !principalCols.Contains(col));\n\n    if (!hasRequiredNonShared)\n        throw new InvalidOperationException(\n            $\"Optional dependent {et.Name} needs a required non-shared property or a required navigation.\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Add a required non-nullable sentinel property (e.g. bool Exists) to optional owned types that contain nested owned types.","Prefer .IsRequired() on ownerships when the dependent always exists.","Avoid nesting owned types under an optional owned type; split to a separate table instead."],"tags":["ef-core","table-sharing","owned-types","model-validation"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}