在用 OR 连接的 where 子句中使用动态谓词的 linq 查询

标签 linq lambda expression

如果向当前查询添加更多限制,则可以在 c# 中轻松创建动态查询。

var list = new List<Item>();
var q = list.AsQueryable();
q = q.Where(x => x.Size == 3);
q = q.Where(x => x.Color == "blue");

在这种情况下,每个新谓词都被添加,并与前一个谓词执行 AND 运算。之前的结果等价于:
q = list.Where(x => x.Size == 3 && x.Color == "blue");

是否有可能达到相同的结果但使用 OR 而不是 AND ?
q = list.Where(x => x.Size == 3 || x.Color == "blue");

这个想法是有可变数量的表达式与 OR 运算符连接。

预期的结果需要以类似于以下伪代码的方式编写:
var conditions = new List<Func<Item, bool>>();

然后迭代条件来构建类似的东西:
foreach(var condition in conditions)
    finalExpression += finalExpression || condition;

最佳答案

另一个可能的解决方案,特别是当有人不想使用外部库时,使用表达式树。

添加以下表达式扩展:

public static Expression<Func<T, bool>> Or<T>(
    this Expression<Func<T, bool>> expr1, 
    Expression<Func<T, bool>> expr2)
{
    var invokedExpr = Expression.Invoke(expr2, expr1.Parameters);
    return Expression.Lambda<Func<T, bool>>(
        Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}

例如,假设您有一个 Container 实体,它具有 InnerContainer 嵌套实体,其中包含两个属性 Name 和 Id。然后您可以通过以下方式使用它:
Expression<Func<Container, bool>> whereQuery = c => c.InnerContainer.Name == "Name1";
whereQuery = whereQuery.Or(c => c.InnerContainer.Name == "Name2");
whereQuery = whereQuery.Or(c => c.InnerContainer.Id == 0);
var result = query
    .Where(whereQuery)
    .ToList();

实现此类查询将产生以下 SQL:
SELECT [x].[Id], [x].[InnerContainerId]
FROM [Containers] AS [x]
LEFT JOIN [InnerContainer] AS [x.InnerContainer] ON [x].[InnerContainerId] = [x.InnerContainer].[Id]
WHERE [x.InnerContainer].[Name] IN (N'Name1', N'Name2') OR ([x].[InnerContainerId] = 0)

通过这种方式,您可以将 lambda 保存在一个集合中并循环遍历它们。

关于在用 OR 连接的 where 子句中使用动态谓词的 linq 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18596847/

相关文章:

c# - 如何从对象列表中删除(通过 linq)重复项

python - 基于 pandas 中的 groupby() 从多列计算

ios - 如何确定两个数学表达式 'sort of' 是否相同?

c - 如何理解[]、()、复合文字运算符、.和 -> 是后缀运算符吗?

c# - 使用 lambda 语法的 linq 连接运算符类型

.net - 多个相似的 linq 查询

c# - Distinct concat 两个 IEnumerables 并标记它是否来自列表 B

java - 在 Java 8 中使用 lambda 表达式时出现错误的非法开头

lambda - Genie 中 vala lambda 的替代品

java - 如何确保在进行除法时不会进行整数转换?