Skip to content

Required owned entity on a TPH derived type is materialized for an unrelated row #38659

Description

@galaxy-atlas

Bug description

Using TPH, a derived type has a required OwnsOne navigation:

efcore-tph-required-owned-repro.zip

modelBuilder.Entity<CircleOverlay>(builder =>
{
    builder.OwnsOne(x => x.Shape);
    builder.Navigation(x => x.Shape).IsRequired();
});

The database contains only a LineOverlay and no CircleOverlay rows. However,
querying the base type still invokes the Circle constructor with null:

await db.Overlays.AsNoTracking().ToListAsync();
CircleOverlay rows in database: 0
Circle constructor called: point is null = True, radius = 0
System.ArgumentNullException: Value cannot be null. (Parameter 'point')

Expected

EF materializes the LineOverlay without invoking the Circle constructor,
because the row discriminator is LineOverlay.

Reproduction

Run the attached project:

dotnet run

Reproduced with:

  • EF Core / SQLite provider 10.0.10
  • .NET 10.0

This appears related to #31353, which was fixed in 8.0.3. Unlike that issue,
this owned navigation is explicitly configured as required. Making it optional
avoids the exception, but changes the model semantics: every CircleOverlay
must have a Circle.

Your code

A complete minimal runnable reproduction project is attached:

[EfCoreTphRequiredOwnedRepro.zip](replace-with-the-link-generated-by-GitHub)

Run it with:


dotnet run

Stack traces

Materializing the base TPH query...
Circle constructor called: point is null = True, radius = 0
Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'point')
   at System.ArgumentNullException.Throw(String paramName)
   at System.ArgumentNullException.ThrowIfNull(Object argument, String paramName)
   at Circle..ctor(String point, Double radius) in C:\myfiles\mytemp\projects\efcore-tph-required-owned-repro\Program.cs:line 62
   at lambda_method84(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
   at Program.<Main>$(String[] args) in C:\myfiles\mytemp\projects\efcore-tph-required-owned-repro\Program.cs:line 32

Verbose output


EF Core version

10.0.10

Database provider

Microsoft.EntityFrameworkCore.Sqlite

Target framework

.NET 10

Operating system

No response

IDE

No response

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions