LINQ questions using contain

JSH 0 Reputation points
2023-08-22T01:18:11.04+00:00

Hello, the source code is shown below.

private async Task<IEnumerable<SearchResource>> GetSearchItemByIdAsync(IEnumerable<string> querys, int offset, int maxResults)
{
	var allQueries = querys.SelectMany(q => q.Split(',')).ToList();

	var songs = await (from sing in context.Sings 

					   join inst in context.Instrumental on sing.InstrumentalId equals inst.Id

					   where allQueries.Contains(inst.NormalizedTitle!)

					   select new { Sing = sing, Instrumental = inst })

					   .OrderBy(s => s.Instrumental.Id).Skip(offset).Take(maxResults).ToListAsync()
	...
}

What I want is to get the words that contain the query, so I used contain, but it only returns if it's an exact match to the words entered in querys.

where allQueries.Any(q => inst.NormalizedTitle.Contains(q))

I tried replacing the where as above, but received the error below.

System.InvalidOperationException: The LINQ expression 'query => EntityShaperExpression: 
    CodeRabbits.KaoList.Song.Instrumental
    ValueBufferExpression: 
        ProjectionBindingExpression: Inner
    IsNullable: False
.NormalizedTitle.Contains(query)' 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'.

What should I do in this case?

thanks - jsh

Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
779 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Bruce (SqlWork.com) 74,936 Reputation points
    2023-08-22T16:12:49.77+00:00

    The lambda expression in EF queries are expression trees, not code. when the query is executed, the expression tree is converted to sql. only limited amount of c# syntax and function calls can be converted to sql.

    the .Contains() confusingly has two translations

    <string1>.Contains(<string2>) => string1 like string2

    ex:

    col1.Contains("x%") => col1 line 'x%'

    <enumeriable>.Contains(<string>) => string in (<enumeriable values as comma separated list>)

    ex:

    var list = new int[] {1,2,3,4}
    ...
    list.Contains(col1) => col1 in (1,2,3,4)

    the following can not be translated to sql

    allQueries.Any(q => inst.NormalizedTitle.Contains(q))

    because allQueries is a c# List<>, and can not be translated to sql except as an "in clause"

    when you ToList() an EF query, the sql is generated and executes. the request is c# objects, so any linq to object queries will work.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.