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

如何使用Linq的Where条件检查字符串列表包含项,解决表达式无法转换报错

错误原因

你遇到的报错是EF Core无法将投影后内存集合RoleNames上的Any()操作转换为SQL语句。你在IQueryable阶段调用了ToList()将角色列表内存化,后续针对该内存集合的过滤逻辑无法被EF Core的查询翻译器识别。

推荐解决方案

将过滤逻辑提前到查询执行前,基于数据库表结构编写可被翻译的过滤条件,过滤完成后再做字段投影。如果你的实体配置了User到UserRole、UserRole到Role的导航属性,可以用更简洁的写法:

// 先构造基础查询
IQueryable<User> query = _context.Users;

// 处理过滤逻辑
if (!string.IsNullOrEmpty(searchText))
{
    query = query.Where(user =>
        // 匹配用户名
        user.UserName.Contains(searchText)
        // 匹配用户关联的任意角色名
        || user.UserRoles.Any(ur => ur.Role.Name.Contains(searchText)));
}

// 过滤完成后投影需要的字段
var data = query.Select(user => new
{
    UserId = user.Id,
    Username = user.UserName,
    RoleNames = user.UserRoles.Select(ur => ur.Role.Name).ToList()
});

如果没有配置导航属性,可以用Join写法实现相同逻辑:

var data = from user in _context.Users
           where string.IsNullOrEmpty(searchText)
               || user.UserName.Contains(searchText)
               // 子查询匹配关联角色
               || (from ur in _context.UserRoles
                   join r in _context.Roles on ur.RoleId equals r.Id
                   where ur.UserId == user.Id
                   select r.Name).Any(r => r.Contains(searchText))
           select new
           {
               UserId = user.Id,
               Username = user.UserName,
               RoleNames = (from ur in _context.UserRoles
                            join r in _context.Roles on ur.RoleId equals r.Id
                            where ur.UserId == user.Id
                            select r.Name).ToList()
           };

以上两种写法的过滤逻辑都会被EF Core翻译为SQL在数据库侧执行,执行效率高,完全符合你的模糊匹配需求。

不推荐的备选方案(仅适合极小数据量场景)

如果业务场景用户量极少,也可以先将全量数据加载到内存再执行过滤,不需要调整过滤逻辑:

// 调用AsEnumerable()切换为LINQ to Objects,后续操作在内存执行
var data = (from user in _context.Users
           select new
           {
               UserId = user.Id,
               Username = user.UserName,
               RoleNames = (from userRole in _context.UserRoles
                            join role in _context.Roles on userRole.RoleId
                            equals role.Id
                            where userRole.UserId == user.Id
                            select role.Name).ToList()
           }).AsEnumerable();

if (!string.IsNullOrEmpty(searchText))
    data = data.Where(x => x.Username.Contains(searchText) || x.RoleNames.Any(r => r.Contains(searchText)));

该方案会先加载所有用户和角色数据到内存,数据量大时会存在严重性能问题,不建议在生产环境使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 17:15:05