146 votes

Linq : ajouter des conditions à la clause where de manière conditionnelle

J'ai une requête comme celle-ci

(from u in DataContext.Users
       where u.Division == strUserDiv 
       && u.Age > 18
       && u.Height > strHeightinFeet  
       select new DTO_UserMaster
       {
         Prop1 = u.Name,
       }).ToList();

Je souhaite ajouter les différentes conditions telles que l'âge, la taille en fonction des conditions fournies à la méthode qui exécute cette requête. Toutes les conditions incluront la division de l'utilisateur. Si l'âge a été fourni, je veux l'ajouter à la requête. De même, si la taille a été fournie, je veux l'ajouter également.

Si cela devait être fait en utilisant des requêtes SQL, j'aurais utilisé le constructeur de chaînes pour les ajouter à la requête principale strSQL. Mais ici, en Linq, je ne peux que penser à utiliser une condition IF où j'écrirais la même requête trois fois, avec chaque bloc IF ayant une condition supplémentaire. Existe-t-il une meilleure façon de procéder ?

253voto

Reed Copsey Points 315315

Si vous n'appelez pas ToList() et votre mapping final vers le type DTO, vous pouvez ajouter Where au fur et à mesure, et construire les résultats à la fin :

var query = from u in DataContext.Users
   where u.Division == strUserDiv 
   && u.Age > 18
   && u.Height > strHeightinFeet
   select u;

if (useAge)
   query = query.Where(u => u.Age > age);

if (useHeight)
   query = query.Where(u => u.Height > strHeightinFeet);

// Build the results at the end
var results = query.Select(u => new DTO_UserMaster
   {
     Prop1 = u.Name,
   }).ToList();

Cela n'entraînera qu'un seul appel à la base de données, ce qui sera tout aussi efficace que d'écrire la requête en une seule fois.

35voto

Yuriy Granovskiy Points 450

J'utilise habituellement le chaînage de méthodes, mais je rencontre le même problème. Et voici l'extension que j'utilise

public static IQueryable<T> ConditionalWhere<T>(
        this IQueryable<T> source, 
        Func<bool> condition,
        Expression<Func<T, bool>> predicate)
    {
        if (condition())
        {
            return source.Where(predicate);
        }

        return source;
    }

Il permet d'éviter les ruptures de chaîne. De même, la même ConditionalOrderBy y ConditionalOrderByDescending sont utiles.

25voto

Matthew Vines Points 14425

Une option.

bool? age = null

(from u in DataContext.Users
           where u.Division == strUserDiv 
           && (age == null || (age != null && u.Age > age.Value))
           && u.Height > strHeightinFeet  
           select new DTO_UserMaster
           {
             Prop1 = u.Name,
           }).ToList();

ou vous pouvez passer à la syntaxe de méthode pour linq et utiliser des conditions if pour attacher des expressions à la clause where.

10voto

Own Points 83

Je l'utilise simplement dans ma clause where comme suit

    public IList<ent_para> getList(ent_para para){
     db.table1.Where(w=>(para.abc!=""?w.para==para.abc:true==true) && (para.xyz!=""?w.xyz==para.xyz:true==true)).ToList();
}

8voto

Melu Points 303

En fonction de certaines conditions, ajouter la condition where ...

from u in DataContext.Users
where u.Division == strUserDiv 
&& u.Age != null ? u.Age > 18 : 1== 1
&& u.Height != null ? u.Height > 18 : 1== 1
&& u.Height != null ? u.Height > 18 : 1== 1
 select new DTO_UserMaster
       {
         Prop1 = u.Name,
       }).ToList();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X