-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Query: compilation error for queries with navigations that also compare same navigation to null #7207
Comments
Still repros on current dev |
Assigning to 1.1.1 in case this is a regression that needs fixing. We can reevaluate based on the repro. |
Verified that this was already broken in 1.0.2, moving out of 1.1.1 |
IQueryable< i had Exception Like This ------------------------------------------------------------------------------------ System.ArgumentException: must be reducible node more SOLUTION 👍 > IQueryable<
|
Still repros in current bits. Simplified repro: class Program
{
static void Main(string[] args)
{
using (var ctx = new MyContext())
{
ctx.Database.EnsureDeleted();
ctx.Database.EnsureCreated();
var query = ctx.Fingerprints
.Where(p => !p.Person.Examined || p.Person == null)
.Select(p => p.Id);
var result = query.ToList();
}
}
}
public class MyContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(@"Server=.;Database=Repro7207;Trusted_Connection=True;MultipleActiveResultSets=True");
}
public DbSet<Person> Persons { get; set; }
public DbSet<Fingerprint> Fingerprints { get; set; }
}
public class Person
{
public int Id { get; set; }
public bool Examined { get; set; }
public Fingerprint Fingerprint { get; set; }
}
public class Fingerprint
{
public int Id { get; set; }
public int? PersonId { get; set; }
public Person Person { get; set; }
} query plan:
|
It looks like that nav rewrite is not expanding through not expression. |
…that also compare same navigation to null Problem was in the optimization that compared navigation to null, specifically: o.Customer == null => c.CustomerId == null If we detected that this optimization could be performed, we assumed that the navigation [o.Customer] is no longer needed, and it was being removed from the navigation joins list. However, if that navigation was also used for another nav access, then it should not have been removed. Fix is to add counter to the NavigationJoins list, and only remove given navigation join from the list, if it's not referenced anywhere else in the query. Also removed some dead code and fixed an issue where we would not apply: c == o.Customer => c.Id == o.CustomerId if CustomerId was optional (i.e. clr type was different than the PK on the other side)
…that also compare same navigation to null Problem was in the optimization that compared navigation to null, specifically: o.Customer == null => c.CustomerId == null If we detected that this optimization could be performed, we assumed that the navigation [o.Customer] is no longer needed, and it was being removed from the navigation joins list. However, if that navigation was also used for another nav access, then it should not have been removed. Fix is to add counter to the NavigationJoins list, and only remove given navigation join from the list, if it's not referenced anywhere else in the query. Also removed some dead code and fixed an issue where we would not apply: c == o.Customer => c.Id == o.CustomerId if CustomerId was optional (i.e. clr type was different than the PK on the other side)
…that also compare same navigation to null Problem was in the optimization that compared navigation to null, specifically: o.Customer == null => c.CustomerId == null If we detected that this optimization could be performed, we assumed that the navigation [o.Customer] is no longer needed, and it was being removed from the navigation joins list. However, if that navigation was also used for another nav access, then it should not have been removed. Fix is to add counter to the NavigationJoins list, and only remove given navigation join from the list, if it's not referenced anywhere else in the query. Also removed some dead code and fixed an issue where we would not apply: c == o.Customer => c.Id == o.CustomerId if CustomerId was optional (i.e. clr type was different than the PK on the other side)
Is there a known workaround for this in version 1.1.2? (Except materializing the data in memory before making the projection) |
You can try comparing a property on an entity to null, rather than the entity itself. E.g.: instead of doing Try: This should circumvent the bug, but you might hit some other issues. Worth to try though. |
Wow, that worked! Thanks a lot! 👌 |
Steps to reproduce
Please see this repo for a repro: https://github.com/alaatm/EF-MustBeReducibleNode
Further technical details
EF Core version: 1.1.0
Database Provider: Microsoft.EntityFrameworkCore.SqlServer
Operating system: Windows 10
IDE: Visual Studio Code
The text was updated successfully, but these errors were encountered: