.netasp.net-coreentity-framework-core

LINQ Query Translation Error with Array of Search Queries in EF Core


I'm trying to filter values in a table based on multiple columns using an array of search queries. My SearchQuery property looks like this:

public string[] SearchQuery { get; set; }

Here's the LINQ query I wrote:

.Where(x => request.SearchQuery == null || request.SearchQuery
    .Any(searchQuery => string.IsNullOrEmpty(searchQuery) ||
        (x.Column1 != null && x.Column1 .Contains(searchQuery)) ||
        (x.Column2 != null && x.Column2 .Contains(searchQuery)) ||
        (x.Column3 != null && x.Column3 .Contains(searchQuery))
))

However, when executing this query, I get the following error:

The LINQ expression 'my-expression' 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.

Additional Context

I'm using the IRepository pattern, and my query is encapsulated in a specification class. Here's how the implementation looks:

public sealed class ListItemsSpecification : Specification<Table>
{
    public ListItemsSpecification(MyRequest request, bool applyPagination = true)
    {
        Query
            .Where(x => request.SearchQuery == null || request.SearchQuery
               .Any(searchQuery => string.IsNullOrEmpty(searchQuery) ||
               (x.Column1 != null && x.Column1.Contains(searchQuery)) ||
               (x.Column2 != null && x.Column2.Contains(searchQuery)) ||
               (x.Column3 != null && x.Column3.Contains(searchQuery))
             ))
            .AsNoTracking();

        if (applyPagination)
            Query.ApplyListRequest(request.OrderBy, request.Sort, request.Offset, request.Limit);
    }
}

How can I rewrite this query so that it can be translated by Entity Framework Core?

I also tried forming the query separately, but, unfortunately, this approach also resulted in the same error


Solution

  • This clause x => request.SearchQuery == null can be removed from linq and placed outside in an if statement.

    You're also trying to loop request.SearchQuery inside linq which might be the one confusing it.

    Once you remove the redundant code, you're left with;

    public ListItemsSpecification(MyRequest request, bool applyPagination = true)
    {
        if (request.SearchQuery != null && request.SearchQuery.Length > 0)
        {
            Query
            .Where(
                x.Column1.Contains(request.SearchQuery) ||
                x.Column2.Contains(request.SearchQuery) ||
                x.Column3.Contains(request.SearchQuery)
            )
            .AsNoTracking();
        }
    
        if (applyPagination)
            Query.ApplyListRequest(request.OrderBy, request.Sort, request.Offset, request.Limit);
    }
    

    If x.Column N is nullable then do

    public ListItemsSpecification(MyRequest request, bool applyPagination = true)
    {
        if (request.SearchQuery != null && request.SearchQuery.Length > 0)
        {
            Query
            .Where(
                x.Column1 != null && x.Column1.Contains(request.SearchQuery) ||
                x.Column2 != null && x.Column2.Contains(request.SearchQuery) ||
                x.Column3 != null && x.Column3.Contains(request.SearchQuery)
            )
            .AsNoTracking();
        }
    
        if (applyPagination)
            Query.ApplyListRequest(request.OrderBy, request.Sort, request.Offset, request.Limit);
    }