efcore icon indicating copy to clipboard operation
efcore copied to clipboard

map two nullable complex properties to same column will result in a NullReferenceException

Open PoKNicolas opened this issue 2 weeks ago • 0 comments

Bug description

I have a base class and several child classes with some of them share some complex properties. I try to map them into one table and want to map same complex properties into the same column. This will result in a NullReferenceException if the property is null. See example code.

With different column names the same setup works.

Your code

using Microsoft.EntityFrameworkCore;

await using var context = new ProductContext();
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();

context.Products.Add(new Product1() { Name = "Product 1" });
await context.SaveChangesAsync();

context.ChangeTracker.Clear();
var product = await context.Products.FirstAsync();
var originalProduct = (Product)context.ChangeTracker.Entries().First().OriginalValues.ToObject();


public sealed class ProductContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseSqlServer(Environment.GetEnvironmentVariable("Test__SqlServer__DefaultConnection"))
            .LogTo(Console.WriteLine, LogLevel.Information)
            .EnableSensitiveDataLogging();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().HasDiscriminator<string>("Discriminator")
            .HasValue<Product1>("Product1").HasValue<Product2>("Product2");
        modelBuilder.Entity<Product1>().ComplexProperty(x => x.Price, p => p.Property(a => a.Amount).HasColumnName("Price"));
        modelBuilder.Entity<Product2>().ComplexProperty(x => x.Price, p => p.Property(a => a.Amount).HasColumnName("Price"));
    }
}

public abstract class Product
{
    public int Id { get; private set; }
    public required string Name { get; set; }
    
}

public class Product1 : Product
{
    public Price? Price { get; set; }
}
public class Product2 : Product
{
    public Price? Price { get; set; }
}

public sealed class Price
{
    public required string Amount { get; init; }
}

Stack traces


Verbose output


EF Core version

10.0.1

Database provider

No response

Target framework

.NET 10

Operating system

No response

IDE

Rider

PoKNicolas avatar Dec 10 '25 12:12 PoKNicolas