-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Fix null check optimization for IQueryable/DbSet types in LINQ queries #36986
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
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: cincuranet <[email protected]>
Co-authored-by: cincuranet <[email protected]>
src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
src/EFCore/Query/Internal/NullCheckRemovingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
dae8232
to
ebcb425
Compare
ebcb425
to
e36862c
Compare
NodeType: ExpressionType.Equal or ExpressionType.NotEqual | ||
} binaryExpression) | ||
{ | ||
var isLeftNull = IsNullConstant(binaryExpression.Left); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: with pattern matching just writing out is ConstantExpression { Value: null }
seems simpler, IMHO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method IsNullConstant
is already there, hence it seems reasonable to use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm proposing to remove it, as a code modernization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case I'd like to do in another PR, because that method exists in other places too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
{ | ||
var nonNullExpression = isLeftNull ? binaryExpression.Right : binaryExpression.Left; | ||
|
||
if (nonNullExpression.Type.IsAssignableTo(typeof(IQueryable))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this correct? What happens if there's a local variable of type DbSet/IQueryable and which really does happen to be null (because of some condition in the user's code)?
(in #35598 it's asserted that this is a regression, I wonder what was the change from 8 to 9 which triggered it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if there's a local variable of type DbSet/IQueryable and which really does happen to be null (because of some condition in the user's code)?
Can you show a code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something like:
using var db = new MyContext();
var ids = someFlag ? db.Items.Select(c => c.Id) : null;
var results = await db.Items.Where(r => ids != null && ids.Contains(r.Id)).ToListAsync();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more note:
(in #35598 it's asserted that this is a regression, I wonder what was the change from 8 to 9 which triggered it)
It would be good to understand this... Apparently this scenario was working before without this special-casing, which we'd ideally not need (it's always better to avoid adding more code/special cases if possible)
I don't think Copilot will be able to do this. So let me do it myself. |
Fixes #35598.