如何将Linq查询Where子句的AND逻辑替换为OR逻辑?
如何将Linq查询的AND过滤逻辑改为OR逻辑?
问题场景
你当前的Linq代码通过循环调用Where来叠加过滤条件,这会导致生成的SQL里多个CompanyCode判断用AND连接——显然这不符合你要匹配任意一个选中公司的需求。
先看下你的原代码:
private IQueryable<viewTable> BaseQuery(Models.TestDataContext db) { IQueryable<viewTable> query = db.viewTables; foreach (string row in gridCompany.GridView.GetSelectedFieldValues("CompanyCode")) query = query.Where(t => t.Comp_Code == row.ToString()); return query; }
它生成的SQL是这样的:
SELECT [t0].[Column] FROM [dbo].[viewTable] AS [t0] WHERE ([t0].[CompanyCode] = 'ALPHA') AND ([t0].[CompanyCode] = 'BETA') ORDER BY [t0].[EditDate] DESC
而你想要的是用OR连接的版本:
SELECT [t0].[Column] FROM [dbo].[viewTable] AS [t0] WHERE ([t0].[CompanyCode] = 'ALPHA') OR ([t0].[CompanyCode] = 'BETA') ORDER BY [t0].[EditDate] DESC
解决方案
方法1:用Contains实现(最简洁推荐)
Linq to SQL原生支持Contains方法,它会自动转换成SQL的IN语句——这和多个OR的逻辑完全等价,而且代码更简洁,性能也相当。
修改后的代码:
private IQueryable<viewTable> BaseQuery(Models.TestDataContext db) { // 先把选中的公司Code收集到一个集合里 var selectedCompanyCodes = gridCompany.GridView.GetSelectedFieldValues("CompanyCode") .Select(row => row.ToString()) .ToList(); IQueryable<viewTable> query = db.viewTables; // 只有当有选中项时才添加过滤条件 if (selectedCompanyCodes.Any()) { query = query.Where(t => selectedCompanyCodes.Contains(t.Comp_Code)); } return query; }
这段代码生成的SQL会是:
SELECT [t0].[Column] FROM [dbo].[viewTable] AS [t0] WHERE [t0].[CompanyCode] IN ('ALPHA', 'BETA') ORDER BY [t0].[EditDate] DESC
IN和你要的OR效果完全一致,而且写法更清爽,优先推荐这种方式。
方法2:手动构建OR表达式(适合复杂场景)
如果你的需求更复杂(比如需要动态组合更多复杂条件),可以通过构建表达式树来手动实现OR逻辑:
using System.Linq.Expressions; private IQueryable<viewTable> BaseQuery(Models.TestDataContext db) { var selectedCompanyCodes = gridCompany.GridView.GetSelectedFieldValues("CompanyCode") .Select(row => row.ToString()) .ToList(); IQueryable<viewTable> query = db.viewTables; // 没有选中项直接返回原查询 if (!selectedCompanyCodes.Any()) return query; // 初始化第一个过滤条件 Expression<Func<viewTable, bool>> predicate = t => t.Comp_Code == selectedCompanyCodes[0]; // 循环叠加OR条件 for (int i = 1; i < selectedCompanyCodes.Count; i++) { string currentCode = selectedCompanyCodes[i]; // 把新的条件和之前的条件用OR合并 predicate = Expression.Lambda<Func<viewTable, bool>>( Expression.OrElse(predicate.Body, Expression.Equal( Expression.Property(predicate.Parameters[0], "Comp_Code"), Expression.Constant(currentCode) )), predicate.Parameters[0] ); } // 应用构建好的OR过滤条件 query = query.Where(predicate); return query; }
这种方法会生成你期望的多个OR连接的SQL语句,适合需要自定义复杂逻辑的场景。
为什么原代码会生成AND?
简单说:每一次调用Where都是在已有查询的基础上追加过滤条件,Linq to SQL会自动把这些独立的过滤条件用AND组合起来。而我们需要的是把所有公司Code的判断合并成一个“满足任意一个即可”的条件,所以不能多次调用Where,而是要把多个条件合并成一个表达式。
内容的提问来源于stack exchange,提问作者lulalandtime
相关产品推荐
相关产品推荐

