2011-07-08 2 views
1

J'ai deux méthodes similaires qui prennent un objet critère (objet muet avec une liste de propriétés), appelez une méthode "CreateExpression" sur cet objet de critère, puis utilisez l'expression retournée pour filtrer les résultats.ajouter dynamiquement plusieurs expressions linq à l'exécution

Un de mes exemples a un argument d'un seul critère, et cela fonctionne sans problème. Ma deuxième méthode prend un List<Criteria> puis essaie de parcourir chaque critère de la liste et de générer l'expression correspondante, puis "et" à l'expression précédente. Le résultat final est supposé être une grande expression que je peux ensuite utiliser dans ma requête linq.

Toutefois, cette deuxième méthode ne fonctionne pas. Quand j'utilise le débogueur, je peux voir le prédicat avec son expression body et lambda en interne, mais quand il frappe le serveur SQL, tout ce qu'il envoie est une instruction select sans aucune clause where.

Voici la méthode qui fonctionne (avec un objet critères):

public static List<Segment> GetByCriteria(Criteria.SegmentCriteria myCriteria) 
     { 
      List<Segment> result = null; 

      List<Segment> qry = db.Segments.AsExpandable<Segment>().Where<Segment>(CreateCriteriaExpression(myCriteria)).ToList<Segment>(); 
      qry = qry.Where<Segment>(CreateCriteriaExpressionForCustomProperties(myCriteria).Compile()).ToList<Segment>(); 


      if (qry != null && qry.Count != 0) 
      { 
       result = qry; 
      } 

      return result; 
     } 

est ici celui qui ne fonctionne pas:

public static List<Segment> GetByCriteria(List<Criteria.SegmentCriteria> myCriteria, Common.MultipleCriteriaMatchMethod myMatchMethod) 
     { 

      List<Segment> result = null; 

      var predicate = PredicateBuilder.True<Segment>(); 
      var customPropertiesPredicate = PredicateBuilder.True<Segment>(); 


      foreach (Criteria.SegmentCriteria x in myCriteria) 
      { 
       if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAll) 
       { 
        predicate = predicate.And(CreateCriteriaExpression(x).Expand()); 
        customPropertiesPredicate = customPropertiesPredicate.And(CreateCriteriaExpressionForCustomProperties(x).Expand()); 
       } 
       else if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAny) 
       { 
        predicate = predicate.Or(CreateCriteriaExpression(x).Expand()); 
        customPropertiesPredicate = customPropertiesPredicate.Or(CreateCriteriaExpressionForCustomProperties(x).Expand()); 
       } 
      } 


      List<Segment> qry = db.Segments.AsExpandable<Segment>().Where<Segment>(predicate.Expand()).ToList<Segment>(); 
      qry = qry.Where<Segment>(customPropertiesPredicate.Expand().Compile()).ToList<Segment>(); 

      if (qry != null && qry.Count != 0) 
      { 
       result = qry; 
      } 

      return result; 
     } 

J'utilise Predicate Builder pour générer l'expression initiale . Je ne crois pas qu'il y ait un problème avec ces méthodes puisqu'elles fonctionnent avec la première méthode (singulière).

Est-ce que quelqu'un sait ce qui se passe ici? J'ai oublié de dire que le backend est un framework d'entité.

Répondre

1

Ok, je l'ai compris.

J'avais besoin d'utiliser la méthode "Expand()" sur TOUS les endroits où j'appelais un prédicat dans les lignes où j'ajoutais le prédicat. Voici la nouvelle version fixe de la boucle foreach dans ma deuxième méthode:

foreach (Criteria.SegmentCriteria x in myCriteria) 
      { 
       Criteria.SegmentCriteria item = x; 
       if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAll) 
       { 
        predicate = predicate.Expand().And<Segment>(CreateCriteriaExpression(item).Expand()); 
        customPropertiesPredicate = customPropertiesPredicate.Expand().And<Segment>(CreateCriteriaExpressionForCustomProperties(item).Expand()); 
       } 
       else if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAny) 
       { 
        predicate = predicate.Expand().Or<Segment>(CreateCriteriaExpression(item).Expand()); 
        customPropertiesPredicate = customPropertiesPredicate.Expand().Or<Segment>(CreateCriteriaExpressionForCustomProperties(item).Expand()); 
       } 
      } 

Et maintenant ça marche! J'ai trouvé des détails à ce sujet également sur cet autre question.

0

À l'intérieur de votre pour chaque boucle, déclarez une variable locale dans ce bloc et définissez sa valeur à la valeur de la variable de boucle.

 foreach (Criteria.SegmentCriteria x in myCriteria) 
     { 
      Criteria.SegmentCriteria temp = x; 
      if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAll) 
      { 
       predicate = predicate.And(CreateCriteriaExpression(temp).Expand()); 
       customPropertiesPredicate = customPropertiesPredicate.And(CreateCriteriaExpressionForCustomProperties(temp).Expand()); 
      } 
      else if (myMatchMethod == Common.MultipleCriteriaMatchMethod.MatchOnAny) 
      { 
       predicate = predicate.Or(CreateCriteriaExpression(temp).Expand()); 
       customPropertiesPredicate = customPropertiesPredicate.Or(CreateCriteriaExpressionForCustomProperties(temp).Expand()); 
      } 
     } 
+0

Donne ce coup, mais le comportement reste le même. Merci quand même! –

Questions connexes