已阅读其他类似问题的回复但我不能使用PredicateBuilder,或复制其来源。我正在尝试我在这里读到的内容:
< https://blogs.msdn.microsoft.com/meek/2008/05/02/linq-to-entities-combining-predicates/
但是,因为我是新手,因此无法将我正在阅读的内容翻译成我正在申请的内容。我创建了一个L2E查询,并试图将一系列OR子句附加到WHERE:
因此简化的代码片段(这个将与以前已经定义的WHERE子句进行AND')
{
"extends": "standard",
"rules": {
"semi": 0
}
}
现在尝试OR:
if (firstParm == "realtor")
query = query.Where(x=> x.A == "realtor");
我知道这也可以通过Union完成,但不清楚语法:
if (secondParm == "clown")
// how to add this one as an OR to the above query:
query = query.OR(x=> x.fool == "clown");
我也引用了:
Combining two expressions (Expression<Func<T, bool>>)
Unable to create a compound Expression<Func<string, bool>> from a set of expressions
但同样,我是LINQ的新手,尤其是Expression Trees,所以需要更多的填充。
答案 0 :(得分:2)
有两种方法可以生成表达式。
使用编译器执行此操作。
Expression<Func<Person, bool>> = p => p.LastName.Contains("A");
限制:可以通过这种方式生成的唯一表达式是LambdaExpression
的实例。此外,提取表达式的一部分并与其他部分结合起来相当复杂。
使用System.Linq.Expressions.Expression
。
为了生成动态表达式,您可以在不同的编译器生成的表达式中进行选择:
// using Record and Records as a placeholder for the actual record type and DbSet property
Expression<Func<Record,bool>> expr;
if (firstParam == "realtor") {
if (secondParam == "clown") {
expr = x => x.A == "realtor" || x.fool == "clown";
} else {
expr = x => x.A == "realtor";
}
} else {
if (secondParam == "clown") {
expr = x => x.fool="clown";
} else {
expr = x => false;
}
}
var ctx = new MyDbContext();
var qry = ctx.Records.Where(expr).Select(x => new {x.A, x.fool});
或者,您可以使用静态方法动态创建表达式:
(将using System.Linq.Expressions;
和using static System.Linq.Expressions.Expression;
添加到文件顶部。)
Expression expr;
var parameter = Parameter(typeof(Record));
if (firstParam == "realtor") {
expr = Equals(
MakeMemberAccess(parameter, typeof(Record).GetProperty("A")),
Constant("realtor")
);
}
if (secondParam == "clown") {
var exprClown = Equals(
MakeMemberAccess(parameter, typeof(Record).GetProperty("fool")),
Constant("clown")
);
if (expr == null) {
expr = exprClown;
} else {
expr = Or(expr, exprClown);
}
}
var lambda = Lambda<Func<Record,bool>>(expr, new [] {parameter});
var ctx = new MyDbContext();
var qry = ctx.Records.Where(lambda).Select(x => new {x.A, x.fool});
在编译时给定一个类型未知的查询,因此引用它的任何变量只能是IQueryable
,而不是IQueryable<T>
:
IQueryable qry = ctx.GetQuery(); //dynamically built query here
var parameter = Parameter(qry.ElementType);
if (firstParam == "realtor") {
expr = Equals(
MakeMemberAccess(parameter, qry.ElementType.GetProperty("A")),
Constant("realtor")
);
}
if (secondParam == "clown") {
var exprClown = Equals(
MakeMemberAccess(parameter, qry.ElementType.GetProperty("fool")),
Constant("clown")
);
if (expr == null) {
expr = exprClown;
} else {
expr = Or(expr, exprClown);
}
}
var lambda = Lambda(expr, new [] {parameter});
//Since we don't have access to the TSource type to be used by the Where method, we have
//to invoke Where using reflection.
//There are two overloads of Queryable.Where; we need the one where the generic argument
//is Expression<Func<TSource,bool>>, not Expression<Func<TSource,int,bool>>
var miWhere = typeof(Queryable).GetMethods().Single(mi => {
mi.Name == "Where" &&
mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Length == 2
});
qry = miWhere.Invoke(null, new [] {qry, lambda});
答案 1 :(得分:0)
或者你可以试试
if (secondParm == "clown")
{
query = query.Where(x=> x.fool == "clown" || x.fool==x.fool);
}
OR
if (secondParm == "clown")
{
query = query.Where(x=> x.fool == "clown" || true );
}