EF Core中多条件EF.Functions.Like无法翻译的解决方法咨询
EF Core 字符串前缀列表过滤的翻译问题解决方法
你遇到的问题是EF Core无法将内存集合的Any嵌套EF.Functions.Like的表达式翻译成SQL,导致查询无法执行。以下是几种数据库端过滤的解决方法:
方法一:EF Core 5.0+ 直接使用StartsWith结合Any
如果你的EF Core版本是5.0及以上,可以直接用StartsWith替代EF.Functions.Like,框架会自动将这个表达式翻译成SQL的多个LIKE OR条件:
var prefixes = new List<string> { "sth", "sth2", "sth3" }; var query = context.Person .Where(p => prefixes.Any(pr => p.Name.StartsWith(pr))) .Select(...);
方法二:用PredicateBuilder构建OR条件(兼容低版本EF Core)
如果使用的是EF Core 3.x及以下版本,可以通过构建动态的OR表达式来实现。你可以自己实现一个简易的PredicateBuilder:
简易PredicateBuilder实现
public static class PredicateBuilder { public static Expression<Func<T, bool>> False<T>() => _ => false; public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right) { var invokedRight = Expression.Invoke(right, left.Parameters.Cast<Expression>()); return Expression.Lambda<Func<T, bool>>( Expression.OrElse(left.Body, invokedRight), left.Parameters ); } }
使用示例
var prefixes = new List<string> { "sth", "sth2", "sth3" }; var predicate = PredicateBuilder.False<Person>(); foreach (var prefix in prefixes) { var currentPrefix = prefix; // 避免闭包陷阱 predicate = predicate.Or(p => EF.Functions.Like(p.Name, $"{currentPrefix}%")); } var query = context.Person.Where(predicate).Select(...);
方法三:参数化原生SQL查询
如果上述方法不适用,可以通过参数化的原生SQL实现,确保不会有SQL注入风险:
var prefixes = new List<string> { "sth", "sth2", "sth3" }; var sqlParams = prefixes.Select((prefix, index) => new SqlParameter($"@prefix{index}", $"{prefix}%") ).ToList(); var likeConditions = string.Join(" OR ", prefixes.Select((_, index) => $"Name LIKE @prefix{index}") ); var query = context.Person .FromSqlRaw($"SELECT * FROM Person WHERE {likeConditions}", sqlParams.ToArray()) .Select(...);
内容的提问来源于stack exchange,提问作者Piotr
相关产品推荐
相关产品推荐

