Skip to content

Incorrect apply projection for complex properties #32911

@tNRevan

Description

@tNRevan

When I combine ComplexProperty and AsSplitQuery with properties mapped to column with equal names, I get wrong values when reading the complex properties. Their values are equal (but they are different instances). If I don't use the AsSplitQuery or rename the columns, the results are correct. See the snippet below.

The code is using Microsoft.EntityFrameworkCore.Sqlite 8.0.1 package.

#nullable enable

void Main()
{
	using (var ctx = new MyContext())
	{
		ctx.Database.EnsureDeleted();
		ctx.Database.EnsureCreated();
		ctx.Add(new Offer 
		{
			Variations = [
				new Variation {
					Payment = new Payment(120, 100),
					Nested = new NestedEntity
					{
						Payment = new Payment(12, 10),
					},
					Nested2 = new NestedEntity2
					{
						Payment = new Payment(24, 20),
					},
				}
			]
		});
		ctx.SaveChanges();
		ctx.ChangeTracker.Clear(); // If I don't clear the change tracker, it also works.
		
		var entity = ctx.Offers
			.Include(e => e.Variations!)
				.ThenInclude(v => v.Nested)
			.Include(e => e.Variations!)
				.ThenInclude(v => v.Nested2)
			.AsSplitQuery() // If I comment this out, it works
			.Single(e => e.Id == 1);
		
		//  The values are equal even when they shouldn't be.
		Console.WriteLine($"Entity {entity.Variations?.Single().Payment}");
		Console.WriteLine($"Nested Entity {entity.Variations?.Single().Nested?.Payment}");
		Console.WriteLine($"Nested Entity2 {entity.Variations?.Single().Nested2?.Payment}");
	}
}

public class MyContext : DbContext
{
	public DbSet<Offer> Offers => Set<Offer>();
	
	protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
	{
	    optionsBuilder.UseSqlite("DataSource=Test.db");
	}
	
	protected override void OnModelCreating(ModelBuilder builder)
	{
		builder.Entity<Variation>().ComplexProperty(p => p.Payment, price =>
		{
		    price.Property(p => p.Netto).HasColumnName("payment_netto"); // If I change the column name to a different than the others, it also works
		    price.Property(p => p.Brutto).HasColumnName("payment_brutto");
		});
		builder.Entity<NestedEntity>().ComplexProperty(p => p.Payment, price =>
		{
		    price.Property(p => p.Netto).HasColumnName("payment_netto");
		    price.Property(p => p.Brutto).HasColumnName("payment_brutto");
		});
		builder.Entity<NestedEntity2>().ComplexProperty(p => p.Payment, price =>
		{
		    price.Property(p => p.Netto).HasColumnName("payment_netto");
		    price.Property(p => p.Brutto).HasColumnName("payment_brutto");
		});
	}
}

public abstract class EntityBase 
{
	[System.ComponentModel.DataAnnotations.Key]
	public int Id {get; set; }
}

public class Offer : EntityBase
{	
	public ICollection<Variation>? Variations { get; set; }
}

public class Variation : EntityBase
{
	public Payment Payment {get; set; } = new Payment(0, 0);

	public NestedEntity? Nested {get; set; }
	public NestedEntity2? Nested2 {get; set; }
}

public class NestedEntity : EntityBase
{
	public Payment Payment {get; set; } = new Payment(0, 0);
}

public class NestedEntity2 : EntityBase
{
	public Payment Payment {get; set; } = new Payment(0, 0);
}

public record Payment(decimal Netto, decimal Brutto);

Include provider and version information

EF Core version: 8.0.1
Database provider: Microsoft.EntityFrameworkCore.Sqlite 8.0.1
Target framework: .NET 8.0
Operating system: Windows 10
IDE: Visual Studio 2022 17.8.5

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions