-
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: Expand Any/All on local collection into predicate with AND/OR #19070
Comments
@AkshayBanifatsyevich Thanks for filing this; we will get back to you with more details after our next triage meeting. |
@smitpatel to show different way to write the query. |
Under the hood, EF6 expanded into following only var searchTerms = query.Replace(" ", "").Split(" ");
var searchResult = await context.Items
.Where(x => EF.Functions.Like(x.Title, $"%{searchTerms[0]}%") || EF.Functions.Like(x.Title, $"%{searchTerms[1]}%"))
.ToListAsync(); To do it dynamically when varying size of searchTerms, you need to drop down to expression tree construction. |
Can any further guidance be provided for workarounds where there is a dynamic number of search terms? @smitpatel suggested "drop down to expression tree construction", is there any suggestion on best practice to accomplish this? The project I am working on has a large number of .Any() queries per above, all of which now throw due to client evaluation after upgrading from 2.2.6 to 3.1.2. Typical predicates: |
Using LINQKit, you can create an extension method to make translating the
However, EF includes a translation for
If you wanted to avoid LINQKit, you would have to create your own |
What's the priority/milestone target for this? This is an EXTREMELY common case used throughout our codebase, blocking our migration. |
Did client evaluation. You can opt-in client evaluation yourself if that is what you want. |
@smitpatel Oh GOD no. In-memory is NOT viable in API scenarios and was a severe mistake to enable in the get-go as it gave a very incomplete representation of framework readiness (thus why the team finally changed this behaviour in 3.x). We are just finally doing our migration from EF6 after EF Core failed miserably in both the EFC 1.x and 2.x timeframes. We were hoping 3.1 is production-ready but after seeing how even simple queries like this aren't yet working it doesn't yet seem to be the case..... |
PS: We would not have to be going through this pain if the team didn't abandon EF6 before EF Core is ready. Are cross-platform migrations EVER going to be supported for EF6? (link) (since clearly EF 3.1 is not prod-ready and I am having deep doubts EFC 5 will be either) |
We have been using EF Core 2.2 and 3.1 successfully in production for more than a year now, so I think you are generalising... |
@ErikEJ not saying you can't. But we have a not THAT complex system, and when you can't even compare a list of stings in a query, let alone the bigger things such as TPT that are missing, along with the slew of bugs and surprises that have come up along the way (150+ issues fixed in 3.0), and a "brand new query system" that brings its own surprises such as the upcoming query splitting Little Big Detail which causes queries to max out on production-size datasets. There are always workarounds you can apply and headaches to take on devoid of business value, but that's not what production-grade entails. We all want it to get there. As of EF Core 3.1 It is frustratingly still behind the value/productivity that life of EF6 entails, and unfortunately for many this means either not adopting or having dual systems set up where we have both EFCore and EF6 where everything that EFCore can do we do, and everything it can't we run through EF6 (a big complexity-add and pain). |
I came up with a workaround, hope it could help you if you are also using SQL Server. In this case, please try changing code as follows: var searchTermsStr = query.Replace(" ", "");
var searchTerms = context.Database.SqlQuery<string>($"select value from string_split({new SqlParameter(nameof(searchTermsStr), searchTermsStr)}, ' ')");
var searchResult = await context.Items
.Where(x => searchTerms.Any(term => x.Title.Contains(term)))
.ToListAsync(); There are two changes:
|
Note: simply expanding Any/All to a series of AND/OR would be a form of dynamic querying. Since different numbers of collection items result in different SQLs, the query wouldn't be cachable (much like Contains with a collection) and cause query plan pollution at the database; it would also be incompatible with precompiled queries/NativeAOT. However, there may be a different, non-dynamic approach, similar to how OPENJSON can be used to make Contains better (link). |
Thank you, it works for me to use |
This should now work out of the box (and efficiently) with queryable primitive collection support (#30426), see this blog post for more details. |
Duplicate of #30426 |
When I have a Where clause with a EF.Functions.Like extension method
Then a runtime "System.InvalidOperationException: The LINQ expression could not be translated." exception is thrown.
Steps to reproduce
Given I have the following code:
When execution reaches the WHERE clause, then the following runtime error is thrown:
According to accepted answer https://stackoverflow.com/a/56941963/8128257 this seemed to work in EF6. Is there a way to get this to work in EF Core 3.0.1 in one round trip to the server as described in the answer?
Further technical details
EF Core version: 3.0.1
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework:. .NET Core 3.0
Operating system: Windows 10 Professional
IDE: Visual Studio 2019 16.3.7
The text was updated successfully, but these errors were encountered: