-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Description
Bug description
There appears to be an issue with resolving queries in the case that a query filter .HasQueryFilter()
has been used. In the provided example calling .ToList()
on query returns 1 record, and the .Count()
returns 2 records.
I believe this is due to the foreign key being required and thus resolving to some kind of inner join that always expects a result. However the query filter means that an inner join is inappropriate.
I first came across this issue with SQL Server, and then produced a simple reproducible version in the attached code using the In Memory Database provider. I have tested this against version 9.0.7 of the packages.
In my real world use case I use these to drive a datagrid. Which I believe is fairly common. I would have also expected possibly rewriting the ParentName assignment might result in a different output:
ParentName = x.Parent != null ? x.Parent.Name : null
but it did not. I personally believe in my example the .ToList()
should return both records, but the bigger issue is the inconsistency.
Your code
public class MyDbContext : DbContext
{
public DbSet<Child> Children { get; set; }
public DbSet<Parent> Parents { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseInMemoryDatabase("MyDatabase");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent>().HasQueryFilter(x => !x.Deleted);
modelBuilder.Entity<Child>().HasQueryFilter(x => !x.Deleted);
base.OnModelCreating(modelBuilder);
}
}
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public Parent Parent { get; set; }
public bool Deleted { get; set; }
}
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public bool Deleted { get; set; }
}
using var context = new MyDbContext();
// Add a new customer
context.Parents.Add(new Parent { Name = "Parent1" });
context.Parents.Add(new Parent { Name = "Parent2" });
context.SaveChanges();
context.Children.Add(new Child { Name = "Child1", ParentId = 1 });
context.Children.Add(new Child { Name = "Child2", ParentId = 2 });
context.SaveChanges();
var parent1 = context.Parents.Where(x => x.Id == 1).FirstOrDefault();
parent1.Deleted = true;
context.SaveChanges();
var query = context.Children.Select(x => new
{
ChildName = x.Name,
ParentName = x.Parent.Name
});
var data = query.ToList();
var count = query.Count();
Console.WriteLine($"Data: {data.Count} Count: {count}");
// OUTPUT: data.Count == 1
// OUTPUT: count == 2
// Note they are not the same(!)
Stack traces
Verbose output
EF Core version
9.0.7
Database provider
SqlServer and InMemoryProvider
Target framework
.NET 9.0
Operating system
Windows 11
IDE
Visual Studio 17.4