Skip to content

Constructor calls when using inheritance with owned entities causes exceptions #31353

Closed

Description

@Jejuni

Description and Code

When using owned entities it is fairly normal to use some sort of constructor validation, like throwing ArgumentNullException for null values.
When an owned type like this is used in an inheritance hierarchy on a child EfCore tries to call the constructor with null values for some reason when the parent DbSet is queried. This then leads to a ArgumentNullException.
This only happens when entities of another type that actually have NULL values in their columns are also present in the table.

Repro

A repo for the problem can be found here: https://github.com/Jejuni/EfCoreInheritanceProblem

Replace the SqlServer connection string in MyDbContext with a valid one for your machine.

Code

Given these entities:

public class Name
{
    public Name(string firstName, string lastName)
    {
        FirstName = firstName ?? throw new ArgumentNullException(nameof(firstName));
        LastName = lastName ?? throw new ArgumentNullException(nameof(lastName));
    }

    public string FirstName { get; }
    public string LastName { get; }
}


public abstract class Parent
{
    public Guid Id { get; set; }
}

public class ChildOne : Parent
{
    public int Number { get; set; }
}

public class ChildTwo : Parent
{
    public Name Name { get; set; }
}

and this configuration:

modelBuilder.Entity<Parent>(b =>
        {
            b.HasDiscriminator<string>("Discriminator")
                .HasValue<ChildOne>("one")
                .HasValue<ChildTwo>("two");
        });

        modelBuilder.Entity<ChildTwo>(b =>
        {
            b.OwnsOne(x => x.Name, nameBuilder =>
            {
                nameBuilder.Property(x => x.FirstName);
                nameBuilder.Property(x => x.LastName);
            });
        });

leads to an exception when the following code is run:

await using (var ctx = new MyDbContext())
{
    await ctx.Database.EnsureDeletedAsync();
    await ctx.Database.EnsureCreatedAsync();
}

await using (var ctx2 = new MyDbContext())
{
    ctx2.ChildOnes.Add(new ChildOne { Number = 2 });

    await ctx2.SaveChangesAsync();
}

await using (var ctx3 = new MyDbContext())
{
    var childOnes = await ctx3.ChildOnes.ToListAsync();
    var childTwos = await ctx3.ChildTwos.ToListAsync();
    // NEXT LINE CAUSES EXCEPTION
    var parents = await ctx3.Parents.ToListAsync();
}

Include stack traces

Stack trace shows the code thrown from user error during execution of SingleQueryingEnumerable:

System.ArgumentNullException
  HResult=0x80004003
  Message=Value cannot be null. (Parameter 'firstName')
  Source=EfCoreInheritanceProblem
  StackTrace:
   at EfCoreInheritanceProblem.Name..ctor(String firstName, String lastName) in Whatever\EfCoreInheritanceProblem\EfCoreInheritanceProblem\Entities.cs:line 7
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.<MoveNextAsync>d__20.MoveNext()

Include provider and version information

EF Core version:
Database provider: Microsoft.EntityFrameworkCore.SqlServer, 7.0.9
Target framework: .NET 7.0
Operating system: Windows 11
IDE: Visual Studio 2022 17.6.5

Activity

  1. self-assigned this
    on Jul 27, 2023
  2. added this to the Backlog milestone on Jul 27, 2023
  3. modified the milestones: Backlog, 8.0.x on Jan 13, 2024
  4. added a commit that references this issue on Jan 14, 2024
    d0ba736
  5. added a commit that references this issue on Jan 23, 2024
    1c728fa
  6. added a commit that references this issue on Jan 29, 2024
    29d3b3b
  7. modified the milestones: 8.0.x, 8.0.3 on Feb 2, 2024
  8. added a commit that references this issue on Feb 7, 2024
    cb3b1b6
  9. removed their assignment
    on Aug 31, 2024
  10. added theissue type on Jun 15, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions