IQueryable: Création dynamique d'un filtrage OR

c# expression-trees iqueryable linq linq-to-entities

Question

J'ai un ensemble de critères de recherche dans ce formulaire:

 member  |  value  |  operator
 --------+---------+---------
 height  |   10    |    >
 height  |    2    |    < 
 name    |  Carl   |   ==

Et je veux interroger tous les objets qui correspondent à l'un de ces critères.

En ce moment, je le fais par:

  • construire une expression pour chacun des critères
  • concaténer chaque expression en utilisant une expression 'OU'
  • construction d'une expression lambda contenant l'expression concaténée
  • passage de l'expression lambda à la méthode IQueryable <>. Where ()

Connaissez-vous le moyen le plus simple de filtrer dinamycalement une collection IQueryable en utilisant un OU consécutif?


BONUS Notre solution:

Basé sur la solution IlyaBuiluk @ CodeProject

 member  |  value  |  operator
 --------+---------+---------
 height  |   10    |    >
 height  |    2    |    < 
 name    |  Carl   |   ==

Réponse acceptée

En termes de performances et de facilité d'implémentation, en quoi est-ce une meilleure approche que d'utiliser la bibliothèque de requêtes dynamiques? Je pense que de cette manière, vous avez un meilleur contrôle sur la sortie SQL de vos arbres d’expression.

Par Raúl Roa


Réponse populaire

Si vous avez un ensemble fixe d'opérateurs et un ensemble fixe de membres, vous pouvez alors l'écrire presque sans traiter directement les arbres d'expression. L'idée est de créer des expressions lambda simples pour différents éléments de code (par exemple, Expression<Func<Entity, string>> pour lire les propriétés d'un membre et similaire pour les opérateurs), puis de les composer pour créer un arbre d'expressions. J'ai décrit la solution ici . Le seul problème est que la composition d'expressions n'est pas directement prise en charge en C #, vous avez donc besoin d'un peu de prétraitement (voir la section "Utilitaires extensibles").

Vous pouvez ensuite stocker les fonctions de base dans un dictionnaire et sélectionner celle qui convient (ou une combinaison de ces fonctions) en fonction de ce que l'utilisateur sélectionne. Par exemple, quelque chose comme:

NorthwindDataContext db = new NorthwindDataContext();

// A query that tests whether a property 
// (specified by 'selector' matches a string value
var queryBuilder = Linq.Func
  ((Expression<Func<Customer, string>> selector, string val) =>
      from c in db.Customers.ToExpandable()
      where selector.Expand(c).IndexOf(val) != -1
      select c);

// Dictionary with supported members...
var dict = new Dictionary<string, Expression<Func<Customer, string>>> 
  { { "CompanyName", c => c.CompanyName },
    { "Country",     c => c.Country },
    { "ContactName", c => c.ContactName } };

// Ask user for a property name & value and Build the query
string field = Console.ReadLine();
string value = Console.ReadLine();
var q = queryBuilder(dict[field], value);

L'article contient également un exemple de composition dynamique des conditions OR ou AND. Je n'ai pas mis à jour le code pendant un moment, il a donc besoin de travail, mais je pense que le projet LINQ KIT contient également une version de cette idée.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi