Linq to Entities Where Or子句

时间:2016-11-07 05:21:43

标签: linq c#-4.0 linq-to-entities where-clause

已阅读其他类似问题的回复但我不能使用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,所以需要更多的填充。

2 个答案:

答案 0 :(得分:2)

有两种方法可以生成表达式。

  1. 使用编译器执行此操作。

    Expression<Func<Person, bool>> = p => p.LastName.Contains("A");
    

    限制:可以通过这种方式生成的唯一表达式是LambdaExpression的实例。此外,提取表达式的一部分并与其他部分结合起来相当复杂。

  2. 使用System.Linq.Expressions.Expression

  3. 中的静态方法

    为了生成动态表达式,您可以在不同的编译器生成的表达式中进行选择:

    // 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 );
  }