efcore icon indicating copy to clipboard operation
efcore copied to clipboard

Why does an optional owned type with required nested owned types fail model validation?

Open meisterfranz opened this issue 1 month ago • 1 comments

Question

I'm building a booking system, and EF Core keeps rejecting my configuration with following error:

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

I want to understand exactly why this is invalid, even though it seems like a natural domain model.

Domain Scenario

HotelRoom may or may not have a BasePrice (some rooms aren’t priced yet during setup).

If BasePrice does exist:

  • It always has a required RegularPrice
  • It may have a SeasonalDiscount
  • SeasonalDiscount, when present, always has:
    • a required DiscountPrice
    • a required DiscountPeriod

So the conceptual structure is:

Room
 └── BasePrice (optional)
       ├── RegularPrice (required)
       └── SeasonalDiscount (optional)
             ├── DiscountPrice (required)
             └── DiscountPeriod (required)

This matches the business logic perfectly.

builder.OwnsOne(r => r.BasePrice, basePrice =>
{
    // Required regular price
    basePrice.OwnsOne(p => p.RegularPrice, regular =>
    {
        regular.Property(p => p.Amount).IsRequired();
        
        regular.OwnsOne(p => p.Currency, currency =>
        {
            currency.Property(c => c.Code).IsRequired();
        });
    });
    basePrice.Navigation(p => p.RegularPrice).IsRequired();

    // Optional discount
    basePrice.OwnsOne(p => p.SeasonalDiscount, discount =>
    {
        // Required nested dependents
        discount.OwnsOne(d => d.DiscountPrice, dp =>
        {
            dp.Property(p => p.Amount).IsRequired();
        });
        discount.Navigation(d => d.DiscountPrice).IsRequired();

        discount.OwnsOne(d => d.DiscountPeriod, period =>
        {
            period.Property(p => p.Start).IsRequired();
            period.Property(p => p.End).IsRequired();
        });
        discount.Navigation(d => d.DiscountPeriod).IsRequired();
    });

    basePrice.Navigation(p => p.SeasonalDiscount).IsRequired(false);
});

// BasePrice itself is optional on Room
builder.Navigation(r => r.BasePrice).IsRequired(false);

❓ My Question

Why does EF Core forbid this shape?

Specifically:

  • Why does EF Core not allow required owned types (DiscountPrice and DiscountPeriod) to exist under an optional owned type (BasePrice → SeasonalDiscount → required children)?
  • Is this limitation fundamental to how EF Core materializes owned entities?
  • Is this considered “by design” or a limitation in EF Core?
  • Are there recommended patterns for modeling business scenarios where:
    • A parent component may be optional
    • But its internal components, when present, are non-optional?

I want to understand the core rule and the reasoning behind it, not just how to work around it.

Thank you — any detailed insight is appreciated.

EF Core version

8.0.11

Database provider

Npgsql.EntityFrameworkCore.PostgreSQL

Target framework

.NET 8

Operating system

macOS Tahoe 26.1

meisterfranz avatar Nov 29 '25 16:11 meisterfranz

I'm a bot. Here are possible related and/or duplicate issues (I may be wrong):

  • https://github.com/dotnet/efcore/issues/28030
  • https://github.com/dotnet/efcore/issues/29868
  • https://github.com/dotnet/efcore/issues/29457

MihuBot avatar Nov 29 '25 16:11 MihuBot