Reputation: 4305
I am trying to develop some dynamic type of code that needs the following complicated query to run.
IEnumerable<string> searchKeys = search.KeySearch.Split(',').Select(key => key.Trim());
var searchedIds = _dbContext.Keys
.Where(key => searchKeys.Any(searchKey => EF.Functions.Like(key.Name, searchKey)))
Actually I want to find the rows containing one of the searchKeys inside. For example if I have searchKeys like this:
var searchKeys = ["name_%", "last_x%];
then I want to find the row for example with name name_alex
or with name last_xaka
.
But ef cores says that it couldn't be translated and suggests either to write a translatable query or do the query in client (which is not appropriate in my problem).
System.InvalidOperationException: The LINQ expression 'DbSet() .Where(k => __searchKeys_0 .Any(searchKey => __Functions_1 .Like( matchExpression: k.Name, pattern: searchKey)))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
So I want to change the query to a translatable one but I don't know that what is the problem and no clue to start fixing it.
Upvotes: 1
Views: 3747
Reputation: 5434
So the following solution should at least work:
var searchKeys = search.KeySearch.Split(',').Select(key => key.Trim());
var queries = new List<IQueryable<Key>>();
foreach (var searchKey in searchKeys)
{
queries.Add(_dbContext.Keys.Where(k => EF.Functions.Like(k.Name, searchKey)));
}
var finalQuery = queries[0];
for (var i = 1; i < queries.Count; i++)
{
finalQuery = finalQuery.Union(queries[i]);
}
var filteredKeys = finalQuery.ToList();
I assume the code to be very unefficient because it will result in multiple UNION
statements.
A more performant option would be to build an expression tree Expression<Func<Key, bool>>
that basically produces the following result: .Where(k => EF.Functions.Like(k.Name, searchKey[0]) || ... || EF.Functions.Like(k.Name, searchKey[5]))
.
Upvotes: 3