如何使用 Linq where 条件检查字符串列表是不是包含任何字符串

Posted

技术标签:

【中文标题】如何使用 Linq where 条件检查字符串列表是不是包含任何字符串【英文标题】:How to use Linq where condition to check if a list of strings contains any string如何使用 Linq where 条件检查字符串列表是否包含任何字符串 【发布时间】:2021-12-11 15:22:48 【问题描述】:

我有一个这样的 LINQ 查询:

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()
           ;

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

结果是这样的:

User Id | Username      | RoleNames
1       | Matt          | [User, Admin]
2       | Jennifer      | [User]
3       | John          | []

但是

x.RoleNames.Any(r => r.Contains(searchText))

不工作,导致 InvalidOperationException:无法翻译 LINQ 表达式“...”。

我想传入一个 searchText 来搜索“用户名”和“角色名称”列。 例如。如果我传入 searchText = 'Jen' 它将返回用户 ID 2,如果我传入 searchText = 'user' 它将返回用户 ID 1 和 2。

任何帮助将不胜感激。

【问题讨论】:

你有导航属性User.Roles,或者类似的吗? 我猜Users 不是一个简单的IEnumerable_context 是一个DbContext,而您正在使用像实体框架这样的ORM。问题是,您的 ORM 不知道如何将您的 Lambda 表达式转换为数据库查询,所以这实际上不是 Linq 问题。 您使用的是什么 LINQ:LINQ to Objects / SQL / EF 6.x / EF Core 2.0 / 2.1 / 3.x / 5.x / 6.x?什么数据库提供商? 使用LINQKit,您可以使用 Predicate Builder 构建可翻译的表达式。 @NetMage,这里没有任何帮助。自定义投影使得在谓词中重用集合变得困难。 【参考方案1】:

虽然理论上可以将此条件转换为 SQL,但您的 EF Core 版本不支持。考虑在定义自定义投影之前进行过滤:

var users = _context.Users.AsQueryable();

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

var data = 
    from user in 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()
    ;

【讨论】:

【参考方案2】:

这可能不是你现在想要的答案,但你可能会在以后回顾它并认为它是正确的答案。

您的 ORM(可能是实体框架)无法将您的 Linq 表达式转换为查询。如果您的项目将有一个小型数据库并且您不需要查询来很好地执行,那么请调整您的表达式,以便 ORM 可以生成一个正常运行的查询,尽管不是最佳的。

如果数据将成为您项目的重要组成部分,那么切换到像 Dapper 这样的轻量级 ORM 并学习数据库的查询语言。使用该查询语言编写最优的参数化查询并产生长期效益。

【讨论】:

以上是关于如何使用 Linq where 条件检查字符串列表是不是包含任何字符串的主要内容,如果未能解决你的问题,请参考以下文章

C# LINQ 与两个不同数据集上的条件 where 子句连接

LINQ to SQL Where 子句可选条件

如何在 Linq 的 Where 条件中使用 IN 运算符

如何在 Linq 的 where 条件下从可为空的日期时间中删除时间部分

Linq to SQL 多个条件 where 子句

C# linq:在同一属性字段的列表中检查多个条件