You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用EF.Functions.Like的表达式树在扩展方法中报错

EF Core 扩展方法 LINQ 翻译失败问题

原可正常执行的查询

直接编写LINQ查询时,这段代码能正常生成SQL并执行:

db.Users.Where(x => arrayOfStringEmail.Any(email => EF.Functions.Like(x.Email, "%" + email + "%")))

封装扩展方法后出现的错误

将上述逻辑封装成扩展方法后,EF Core抛出翻译错误:

The LINQ expression 'x => x.Email' 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'.

问题扩展方法代码

出错的扩展方法实现如下:

public static IQueryable<TSource> WhereLike<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, object>> expression, params string[] words)
{
    return source.Where(x => words.Any(word => EF.Functions.Like(expression, "%" + word + "%")));
}

期望调用方式

希望能通过以下方式调用扩展方法:

db.Users.WhereLike(x => x.Email, arrayOfStringEmail);

问题原因

原扩展方法的核心问题是:直接将传入的expression(如x=>x.Email)传入EF.Functions.Like时,EF Core无法识别该表达式中的参数x与Where方法中的参数x是同一个变量,导致无法将整个逻辑翻译成SQL语句。

修复后的扩展方法

通过手动构建表达式树,将成员访问逻辑与多关键词Like逻辑组合,让EF Core能正确翻译:

using System.Linq.Expressions;
using Microsoft.EntityFrameworkCore;

public static class QueryableExtensions
{
    public static IQueryable<TSource> WhereLike<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, string>> expression, params string[] words)
    {
        if (words == null || words.Length == 0)
            return source;

        var memberExpr = expression.Body as MemberExpression;
        if (memberExpr == null)
            throw new ArgumentException("表达式必须是字符串类型的成员访问,例如 x => x.Email");

        var parameter = expression.Parameters[0];
        Expression predicate = null;

        foreach (var word in words)
        {
            var likeCall = Expression.Call(
                typeof(EF.Functions),
                nameof(EF.Functions.Like),
                Type.EmptyTypes,
                memberExpr,
                Expression.Constant("%" + word + "%")
            );

            predicate = predicate == null ? likeCall : Expression.OrElse(predicate, likeCall);
        }

        var lambda = Expression.Lambda<Func<TSource, bool>>(predicate, parameter);
        return source.Where(lambda);
    }
}

修复说明

  1. 将表达式参数类型从Expression<Func<TSource, object>>改为Expression<Func<TSource, string>>,确保传入的成员是字符串类型,匹配EF.Functions.Like的参数要求。
  2. 手动解析传入的成员表达式(如x.Email),并为每个关键词构建对应的Like调用表达式。
  3. 用OrElse将多个Like条件连接,实现原查询中Any的逻辑(只要匹配任意一个关键词即可)。
  4. 最终构建完整的Lambda表达式传入Where方法,EF Core可以正确将其翻译成SQL的OR组合LIKE语句。

内容的提问来源于stack exchange,提问作者derodevil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 22:00:09