0

我有一個查詢:如下創建一個新的動態的IQueryable

var query = from x in context.Employees 
    where (x.Salary > 0 && x.DeptId == 5) || x.DeptId == 2 
    order by x.Surname 
    select x; 

以上是原來的查詢和回報假設1000個員工實體。

我現在想用第一次查詢解構並重新創建一個新的查詢應該是這樣的:

var query = from x in context.Employees 
    where ((x.Salary > 0 && x.DeptId == 5) || x.DeptId == 2) && (x,i) i % 10 == 0 
    order by x.Surname 
    select x.Surname; 

該查詢將返回100個姓氏。

語法可能不正確,但我需要做的是附加一個附加的where子句並將select修改爲單個字段。

我一直在尋找ExpressionVisitor,但我不完全確定如何基於現有查詢創建新的查詢。

任何指導,將不勝感激。謝謝。

回答

0

在表達式訪問者中,您可以重寫方法調用。檢查方法是否爲Queryable。在哪裏,如果是,方法第二個參數是類型爲lambda表達式的帶引號的表達式。釣魚它,你可以擰它。

static void Main() 
    { 
     IQueryable<int> queryable = new List<int>(Enumerable.Range(0, 10)).AsQueryable(); 
     IQueryable<string> queryable2 = queryable 
      .Where(integer => integer % 2 == 0) 
      .OrderBy(x => x) 
      .Select(x => x.ToString()); 
     var expression = Rewrite(queryable2.Expression); 
    } 

    private static Expression Rewrite(Expression expression) 
    { 
     var visitor = new AddToWhere(); 
     return visitor.Visit(expression); 
    } 

    class AddToWhere : ExpressionVisitor 
    { 
     protected override Expression VisitMethodCall(MethodCallExpression node) 
     { 
      ParameterExpression parameter; 
      LambdaExpression lambdaExpression; 
      if (node.Method.DeclaringType != typeof(Queryable) || 
       node.Method.Name != "Where" || 
       (lambdaExpression = ((UnaryExpression)node.Arguments[1]).Operand as LambdaExpression).Parameters.Count != 1 || 
       (parameter = lambdaExpression.Parameters[0]).Type != typeof(int)) 
      { 
       return base.VisitMethodCall(node); 
      } 
      return Expression.Call(
       node.Object, 
       node.Method, 
       this.Visit(node.Arguments[0]), 
       Expression.Quote(
        Expression.Lambda(
         lambdaExpression.Type, 
         Expression.AndAlso(
          lambdaExpression.Body, 
          Expression.Equal(
           Expression.Modulo(
            parameter, 
            Expression.Constant(
             4 
            ) 
           ), 
           Expression.Constant(
            0 
           ) 
          ) 
         ), 
         lambdaExpression.Parameters 
        ) 
       ) 
      ); 
     } 
    } 
}