-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
Bug description
When using EF Core 10 relational ComplexCollection (JSON) mapping on a child entity and a DbContext-level query filter on that child, including the child navigation from the parent results in SQL which references an unselected/invalid column for the ComplexCollection. This causes an SQL exception (Invalid column name) when the FK is optional (nullable), so the result is a Left Join. If it is required then it works as it should.
Your code
#:package Microsoft.EntityFrameworkCore@10.0.0
#:package Microsoft.EntityFrameworkCore.SqlServer@10.0.0
#:property PublishAot=false
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
var connectionString = "Server=(localdb)\\MSSQLLocalDB;Database=EfCoreJoinRepro;Trusted_Connection=True;MultipleActiveResultSets=true";
var options = new DbContextOptionsBuilder<TestContext>()
.UseSqlServer(connectionString)
.EnableSensitiveDataLogging()
.Options;
try
{
using (var context = new TestContext(options))
{
context.Database.EnsureDeleted();
context.Database.EnsureCreated();
// Seed data
var child = new Child
{
Id = Guid.NewGuid(),
IsPublic = true,
CareNeeds =
[
new() { Topic = "Physical Care", Answer = "Needs assistance with mobility" }
],
};
var parent = new Parent
{
Id = Guid.NewGuid(),
Child = child
};
context.Childs.Add(child);
context.Parents.Add(parent);
context.SaveChanges();
Console.WriteLine("✓ Data seeded successfully!\n");
}
using (var context = new TestContext(options))
{
try
{
var parent = await context.Parents
.Include(p => p.Child)
.FirstOrDefaultAsync();
}
catch (Exception ex)
{
Console.WriteLine($"Exception Type: {ex.GetType().Name}");
Console.WriteLine($"Message: {ex.Message}");
Console.WriteLine("---------------------------------------");
var queryString = context.Parents
.Include(p => p.Child)
.ToQueryString();
Console.WriteLine("Generated SQL Query:");
Console.WriteLine(queryString);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"Setup failed: {ex.Message}");
if (ex.InnerException != null)
Console.WriteLine($"Inner: {ex.InnerException.Message}");
}
public sealed class TestContext(DbContextOptions<TestContext> options) : DbContext(options)
{
public DbSet<Parent> Parents => Set<Parent>();
public DbSet<Child> Childs => Set<Child>();
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfigurationsFromAssembly(typeof(TestContext).Assembly);
// This query filter is the key to reproducing the bug
// When applied to Child, EF Core fails to properly generate column names for ComplexCollections
builder.Entity<Child>().HasQueryFilter("CategoryProtection", child =>
child.IsPublic
);
}
}
public class Parent
{
public Guid Id { get; set; }
public Child? Child { get; set; }
//The bug only occurs when this is nullable, so for Left Joins. Inner Joins work fine.
public Guid? ChildId { get; set; }
}
public class Child
{
public Guid Id { get; set; }
public Parent Parent { get; set; } = null!;
public bool IsPublic { get; set; }
public required List<CareNeedAnswer> CareNeeds { get; set; } = [];
}
public record CareNeedAnswer
{
public string Topic { get; set; } = string.Empty;
public string? Answer { get; set; }
public sealed class ChildConfiguration : IEntityTypeConfiguration<Child>
{
public void Configure(EntityTypeBuilder<Child> builder)
{
builder.ComplexCollection(e => e.CareNeeds, cb => cb.ToJson());
builder.HasOne<Parent>()
.WithOne(p => p.Child)
.HasForeignKey<Parent>(p => p.ChildId)
.OnDelete(DeleteBehavior.Cascade);
}
}
}Stack traces
Exception Type: SqlException
Message: Invalid column name 'CareNeeds'.
---------------------------------------
Generated SQL Query:
SELECT [p].[Id], [p].[ChildId], [p].[ChildId1], [c0].[Id], [c0].[IsPublic], [c0].[CareNeeds]
FROM [Parents] AS [p]
LEFT JOIN (
SELECT [c].[Id], [c].[IsPublic]
FROM [Childs] AS [c]
WHERE [c].[IsPublic] = CAST(1 AS bit)
) AS [c0] ON [p].[ChildId] = [c0].[Id]
Verbose output
EF Core version
10.0.0
Database provider
Microsoft.EntityFrameworkCore.SqlServer
Target framework
.Net 10
Operating system
Windows 11
IDE
No response