0

J'ai une requête comme suit:L'utilisation d'un IQueryable existant pour créer une nouvelle dynamique IQueryable

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

Ce qui précède est la requête initiale et retourne disons 1000 entités employés.

Je voudrais maintenant utiliser la première requête de déconstruire et de recréer une nouvelle requête qui ressemblerait à ceci:

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; 

Cette requête retournerait 100 noms de famille.

La syntaxe est probablement incorrecte, mais ce que je dois faire est de joindre une clause where supplémentaire et de modifier le select à un seul champ.

J'ai regardé dans le ExpressionVisitor mais je ne suis pas entièrement sûr de savoir comment créer une nouvelle requête basée sur une requête existante.

Toute aide serait appréciée. Merci.

Répondre

0

Dans un visiteur d'expression, vous devez remplacer l'appel de méthode. Vérifiez si la méthode est Queryable.Where, et si c'est le cas, le second paramètre methods est une expression entre guillemets de type expression lambda. Fish it out et vous pouvez visser avec elle.

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