IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entity Framework Discussion :

Linq, predicate assez complexe


Sujet :

Entity Framework

  1. #1
    Membre expérimenté
    Avatar de jbrasselet
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Mars 2006
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 022
    Points : 1 413
    Points
    1 413
    Par défaut Linq, predicate assez complexe
    Bonjour,

    je suis sur une page de recherche d'un objet dans laquelle il est possible de remplir une textbox avec des mots clés séparés par des espaces.

    J'attaque ma base de données via EntityFramework en créant des requêtes linq.

    Mon objet recherché à un identifiant fonctionnel (CartoEntry) et un code (CartoEntry_CodBasicat).
    Si ma zone de mots clés contient 2 mots (A et B), je dois avoir un where qui ressemble à ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (CartoEntry like '%A%' and CartoEntry like '%B%') or (CartoEntry_CodBasicat like '%A%' and CartoEntry_CodBasicat like '%B%')
    Actuellement j'ai ma requête qui fait un select puis je lui applique les filtres :
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var requete = from obj in bdd.T_CartoEntry_Description
                              orderby obj.CartoEntry
                              select new CartoEntryDto { CartoEntryId = obj.CartoEntry, CartoEntryBasicat = obj.CartoEntry_CodBasicat, CartoEntryStatus = obj.CartoEntry_Status, CartoEntryObjectType = obj.CartoEntry_Object_Type, CartoEntryOrigin = obj.CartoEntry_Origin };
    
                // GERER les restrictions
                if (!String.IsNullOrEmpty(dto.Letter)) { requete = requete.Where(p => p.CartoEntryId.StartsWith(dto.Letter)); }
                if (!String.IsNullOrEmpty(dto.Keyword)) {
                   // ICI est mon problème               
                }
    
                // EXECUTER la requête
                list = requete.ToList();

    Auriez-vous une piste ?
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai.

  2. #2
    Membre éclairé
    Homme Profil pro
    Développeur / architecte
    Inscrit en
    Juillet 2009
    Messages
    473
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur / architecte

    Informations forums :
    Inscription : Juillet 2009
    Messages : 473
    Points : 674
    Points
    674
    Par défaut
    Je sais pas, naïvement je me dis que ça devrait ressembler à ça:
    Code c# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    var requete = from obj in bdd.T_CartoEntry_Description
                              orderby obj.CartoEntry
                              select new CartoEntryDto { CartoEntryId = obj.CartoEntry, CartoEntryBasicat = obj.CartoEntry_CodBasicat, CartoEntryStatus = obj.CartoEntry_Status, CartoEntryObjectType = obj.CartoEntry_Object_Type, CartoEntryOrigin = obj.CartoEntry_Origin };
    
                // GERER les restrictions
                if (!String.IsNullOrEmpty(dto.Letter)) { requete = requete.Where(p => p.CartoEntryId.StartsWith(dto.Letter)); }
                if (!String.IsNullOrEmpty(dto.Keyword)) {
                   // ICI est mon problème        
                  var ks = dto.Keyword.Split(' ');
                  foreach(string k in  ks)
                  {
                      requete = requete.Where(r=>r.CartoEntry.Contains(k) ||  r.CartoEntry_CodBasicat.Contains(k));
                  }
                }
    
                // EXECUTER la requête
                list = requete.ToList();

    J'ai inversé les condition and/or, mais je pense que dans ce cas ça revient au même.

  3. #3
    Membre expérimenté
    Avatar de jbrasselet
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Mars 2006
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 022
    Points : 1 413
    Points
    1 413
    Par défaut
    Ca ne fonctionne pas.
    En effet imaginons que j'ai deux mots A et B dans mon keyword.
    A existe dans CartoEntry mais pas B et B dans CodBasicat mais pas A

    Moi je veux qu'il ne me ramène rien.
    Avec ton exemple, il me ramènera ma ligne.
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai.

  4. #4
    Membre éclairé
    Homme Profil pro
    Développeur / architecte
    Inscrit en
    Juillet 2009
    Messages
    473
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur / architecte

    Informations forums :
    Inscription : Juillet 2009
    Messages : 473
    Points : 674
    Points
    674
    Par défaut
    Effectivement. A ce moment là je ne vois que la possibilité de passer par les expression trees...

  5. #5
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 080
    Points
    8 080
    Par défaut
    En effet, il faut que tu chaines des OU car chainer des Where ca revient à chainer des ET.
    J'ai écrit un petit article de blog à ce sujet:
    http://blog.ou-bien.net/post/2011/07...ynamique).aspx

    Cela consiste en un petit helper:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public Expression<Func<T1,bool>> BuildOr<T1, T2>(Expression<Func<T1, T2, bool>> selector, IEnumerable<T2> args)
     {
         // Initialisation: faux OU a = a
         var q = (Expression<Func<T1,bool>>)(u=>false);
     
         foreach (var element in args)
         {
             // Invocation du selecteur en précisant que le premier paramètre du selecteur est le premier paramètre de la fonction finale
             // et que le second paramètre du selecteur est l'item courant dans la boucle
             var t1 = Expression.Invoke(selector, q.Parameters[0], Expression.Constant(element));
     
                       // OU avec les précédents
             var t2 = Expression.OrElse(q.Body, t1);
             q = Expression.Lambda<Func<T1,bool>>(t2, q.Parameters[0]);
         }
     
         return q;
     }
    Qui s'utilise comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Employees.Where(BuildOr((Employees e, String ch) => e.LastName.Contains(ch), filterList3)).Select (e => e.LastName).Dump();
    Employees.Where(BuildOr((Employees e, int year) => e.BirthDate.HasValue && year <= e.BirthDate.Value.Year && e.BirthDate.Value.Year < year + 10, filterList2)).Select (e => e.LastName).Dump();

  6. #6
    Membre expérimenté
    Avatar de jbrasselet
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Mars 2006
    Messages
    1 022
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 022
    Points : 1 413
    Points
    1 413
    Par défaut
    Je vais regarder ça, pour le moment je suis parti sur une construction de requête "à la main".
    L'urgent est fait, l'impossible est en cours, pour les miracles prévoir un délai.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. combobx assez complexe
    Par stéphanie123 dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 14/05/2008, 22h53
  2. Réponses: 6
    Dernier message: 21/01/2008, 12h09
  3. Réponses: 13
    Dernier message: 12/10/2007, 09h09
  4. Curseur dynamique assez complexe...
    Par yiuche dans le forum Delphi
    Réponses: 7
    Dernier message: 20/03/2007, 11h55
  5. [RegEx] preg_replace assez complexe
    Par Info-Rital dans le forum Langage
    Réponses: 2
    Dernier message: 25/11/2005, 13h28

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo