C# 如何在LINQ中建立动态OR查询?

C# 如何在LINQ中建立动态OR查询?,c#,linq,C#,Linq,我正在尝试用link动态创建一个where子句。 现在,创建类似于选择产品的东西,其中x=123、y=349和w=948是没有问题的。我只是在添加额外的Where过滤器。 products=products.Where(product=>product.Property==123) 但现在我有一个未知数量的值,应该用OR运算符测试。SQL应该类似于选择产品,其中x=123或x=499或x=998。。和n个或更多的建立一个数字列表以进行检查,并执行以下操作: var idsToCheck = ne

我正在尝试用link动态创建一个where子句。 现在,创建类似于
选择产品的东西,其中x=123、y=349和w=948
是没有问题的。我只是在添加额外的Where过滤器。
products=products.Where(product=>product.Property==123)


但现在我有一个未知数量的值,应该用OR运算符测试。SQL应该类似于选择产品,其中x=123或x=499或x=998。。和n个或更多的

建立一个数字列表以进行检查,并执行以下操作:

var idsToCheck = new List<int>{123, 789, 654}; //Build from dynamic list
products = products.Where(x => idsToCheck.Contains(x.Id));
var idsToCheck=新列表{123789654}//从动态列表生成
products=products.Where(x=>idsToCheck.Contains(x.Id));
如有需要,可为v和w复制上述内容

var idsToCheck = new List<int>{123, 789, 654}; //Build from dynamic list
products = products.Where(x => idsToCheck.Contains(x.Id));

var propertyToCheck = new List<int>{123, 789, 654};//Build from dynamic list
products = products.Where(x => propertyToCheck.Contains(x.Property));

var numberToCheck = new List<int>{123, 789, 654};
products = products.Where(x => numberToCheck.Contains(x.Number));
var idsToCheck=新列表{123789654}//从动态列表生成
products=products.Where(x=>idsToCheck.Contains(x.Id));
var-propertyToCheck=新列表{123789654}//从动态列表生成
products=products.Where(x=>propertyToCheck.Contains(x.Property));
var numberToCheck=新列表{123789654};
products=products.Where(x=>numberToCheck.Contains(x.Number));

如果要检查的值已作为可枚举项传入,则无需构建xxxToCheck集合。您只需对原始文件执行
.Contains

您可以在列表中使用Contains,也可以使用如下等式:

  products.Where(product => (product.Property == 123) || (product.Property == 499) || (product.Property == 998));

如果您想从多个where子句组合OR查询,那么您确实需要在where子句中组合谓词。毕竟,链接where子句将是一个AND

因此,如果您有以下谓词:

Func<Product, bool> w1 = p => p.x == 123;
Func<Product, bool> w2 = p => p.y == 349;
Func<Product, bool> w3 = p => p.w == 948;
Func<Product, bool> w4 = p => p.Property == 123;
Func<Product, bool> w5 = p => p.x == 499;
Func<Product, bool> w6 = p => p.x == 998;
Func w1=p=>p.x==123;
Func w2=p=>p.y==349;
Func w3=p=>p.w==948;
Func w4=p=>p.Property==123;
Func w5=p=>p.x==499;
Func w6=p=>p.x==998;
您可以定义以下扩展方法来访问或访问它们:

public static Func<T, bool> Or<T>(this Func<T, bool> @this, Func<T, bool> that)
{
    return t => @this(t) || that(t);
}
public static Func Or(this Func@this,Func that)
{
返回t=>@this(t)| | that(t);
}
现在你可以写:

var products1 = products.Where(w1.Or(w5).Or(w6));

var products2 = products.Where(
    ((Func<Product, bool>)(p => p.x == 123))
        .Or(p => p.y == 349)
        .Or(p => p.Property == 123));
var products1=产品,其中(w1.或(w5).或(w6));
var products2=产品。其中(
((Func)(p=>p.x==123))
.或(p=>p.y==349)
或(p=>p.Property==123));
如果要使用子句列表,请添加此扩展方法:

public static Func<T, bool> Or<T>(this IEnumerable<Func<T, bool>> @this)
{
    return @this.Aggregate((Func<T, bool>)(t => true), (a, t) => a.Or(t));
}
公共静态函数或(this IEnumerable@this)
{
返回@this.Aggregate((Func)(t=>true),(a,t=>a.Or(t));
}
现在你可以写:

var predicates = new List<Func<Product, bool>>()
{
    p => p.x == 123,
    p => p.w == 948,
    p => p.Property == 123,
    p => p.x == 998,
};

var products3 = products.Where(predicates.Or());
var谓词=新列表()
{
p=>p.x==123,
p=>p.w==948,
p=>p.属性==123,
p=>p.x==998,
};
var products3=products.Where(谓词或());
如果您是针对
IQueryable
提供程序编写的,那么您需要使用
Expression
而不仅仅是
Func

然后您需要这些扩展方法:

public static Expression<Func<T, bool>> Or<T>(
    this Expression<Func<T, bool>> @this,
    Expression<Func<T, bool>> that)
{
    var param =
        Expression
            .Parameter(typeof(T), "t");
    var body =
        Expression
            .Or(
                Expression
                    .Invoke(@this, param),
                Expression
                    .Invoke(that, param));
    return
        Expression
            .Lambda<Func<T, bool>>(body, param);
}

public static Expression<Func<T, bool>> Or<T>(
    this IEnumerable<Expression<Func<T, bool>>> @this)
{
    return @this.Aggregate((Expression<Func<T, bool>>)(t => true), (a, t) => a.Or(t));
}
公共静态表达式或(
这个表达式@this,
表达(即)
{
变量参数=
表示
.参数(类型为(T),“T”);
变位体=
表示
.或(
表示
.Invoke(@this,param),
表示
.调用(that,param));
回来
表示
.Lambda(主体,参数);
}
公共静态表达式或(
this(可数@this)
{
返回@this.Aggregate((表达式)(t=>true),(a,t=>a.Or(t));
}
调用代码的工作原理仍然相同:

var predicatesX = new List<Expression<Func<Product, bool>>>()
{
    p => p.x == 123,
    p => p.w == 948,
    p => p.Property == 123,
    p => p.x == 998,
};

var products3X = products.Where(predicatesX.Or());
var-predictESX=新列表()
{
p=>p.x==123,
p=>p.w==948,
p=>p.属性==123,
p=>p.x==998,
};
var products3X=products.Where(predictESX.Or());

这就是你要找的吗?

我希望上面查询的SQL是
SELECT Product WHERE x IN(123,499,998)
是的,你是对的,SQL描述得更好一些!