-
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
Convert multiple equality/in-equality on same column joined by Or/Else into SQL IN expression #20003
Comments
|
@arthur-liberman I have fixed a similar issue in 3.0, but it may be because my values are split into buckets of factors of 2. Where is the duplicate? |
I just searched for "nested too deeply" in the issues section, but now that I've taken another look none of the issues listed are the same as mine, so I'll reopen this. |
Well, part of the issue is hat SQL has no problem with multiple OR to start with - there is no need to use brackets like that and nest them. The seoncd is that - despite all issues with the IN statement, the IN statement is way better than tons of OR in scenarios like this. I would call the 3.1 code defective because it does get way overly complex. |
@NetTecture In with hard coded parameter values is not ideal, imho. @arthur-liberman you must share a repro if.you want help. |
@ErikEJ I updated the OP with a full code example. Also, I agree that In with hard coded parameters isn't ideal, but sometimes there are legacy reasons for having to resort to using it like this. It should still work as expected. |
We don't convert multiple ORs to In Expression in 3.x. We had that optimization since 2.x translation pipeline internally we generated that. In 3.x we don't generate that internally and users could rewrite query to use contains. We will add this some time in future. Using |
@smitpatel I understand, but even so, the way that the SQL query is created from the ORs is incorrect. |
@arthur-liberman - I understand the way you want to see it and for humans it is obvious readable choice but expression tree does not work that way. Since it is OR & equality, they are BinaryExpression. So it generates nice big binary tree which compiler generates right skewed. |
@smitpatel Is there no way around this? If anybody has any suggestion on how to better approach this, I'd be glad to hear them. |
return dbContext.Items
.Where(i => new [] { 4, 5, 1, 7, 12, 15}.Contains(i.Id))
.Select(i => new Dto { Id = i.Id })
.ToList(); You can just initialize an array. As long as it is a mapped scalar type it works. |
Thanks! public IList<Dto> ExecuteQuery()
{
using (var dbContext = new MyDbContext())
{
return dbContext.Items
.Where("(new [] { 4,5,1,7,12,15 }).Contains(Id)")
.Select(i => new Dto { Id = i.Id })
.ToList();
}
} |
Current effort to reduce nesting (with a help from a very smart friend!) - and my parameter count is factors of 2!
|
This also has a duplicate |
cosmos improvement is tracked by #12635 |
…joined by Or/Else into SQL IN expression Various optimizations to queries with IN: - a == X || a == Y -> a IN (X, Y) - a != X && a != Y -> a NOT IN (X, Y) - a IN (X) -> a == X - a IN (X, Y) || a IN (Z, W) -> a IN (X, Y, Z, W) - a IN (X, Y, Z) && a IN (Y, Z, W) -> a IN (Y, Z) Fixes #20003
…joined by Or/Else into SQL IN expression Various optimizations to queries with IN: - a == X || a == Y -> a IN (X, Y) - a != X && a != Y -> a NOT IN (X, Y) - a IN (X) -> a == X - a IN (X, Y) || a IN (Z, W) -> a IN (X, Y, Z, W) - a IN (X, Y, Z) && a IN (Y, Z, W) -> a IN (Y, Z) Fixes #20003
…joined by Or/Else into SQL IN expression Various optimizations to queries with IN: - a == X || a == Y -> a IN (X, Y) - a != X && a != Y -> a NOT IN (X, Y) - a IN (X) -> a == X - a IN (X, Y) || a IN (Z, W) -> a IN (X, Y, Z, W) - a IN (X, Y, Z) && a IN (Y, Z, W) -> a IN (Y, Z) Fixes #20003
…joined by Or/Else into SQL IN expression Various optimizations to queries with IN: - a == X || a == Y -> a IN (X, Y) - a != X && a != Y -> a NOT IN (X, Y) - a IN (X) -> a == X - a IN (X, Y) || a IN (Z, W) -> a IN (X, Y, Z, W) - a IN (X, Y, Z) && a IN (Y, Z, W) -> a IN (Y, Z) Fixes #20003
We generate some Where expressions dynamically in our product. In some situations we pass a long list of values.
In 2.2 this translated into an
IN
expression and was handled correctly.In 3.1 it translates to a series of OR expressions with each consecutive expression being nested in brackets.
The following example produces drastically different SQL code. This also reproduces when we use Devart Oracle provider.
Steps to reproduce
Both
Where
clauses in the example produce identical SQL in each .NET Core version..NET Core 3.1:
.NET Core 2.2:
With enough elements in the
IN
expression, we end up exceeding the allowed nest depth and the SQL server throws an exception.I'm not sure whether this a dup, but I couldn't find any other open issues describing this problem.
Further technical details
EF Core version: 3.1.2
Database provider: Microsoft.EntityFrameworkCore.SqlServer, Devart Oracle provider
Target framework: .NET Core 3.1.2
Operating system: Visual Studio 2019 16.4, Visual Studio Code
The text was updated successfully, but these errors were encountered: