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 :

Est-il possible de faire des Clauses Where conditionnelles avec EF ? [Débutant]


Sujet :

Entity Framework

  1. #1
    Nouveau membre du Club
    Inscrit en
    Juillet 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Juillet 2007
    Messages : 42
    Points : 33
    Points
    33
    Par défaut Est-il possible de faire des Clauses Where conditionnelles avec EF ?
    Bonjour,

    J'ai dans mon application, une partie qui affiche des entrées d'un log. J'ai ajouté sur mon masque la possibilité de filtrer les entrées du logs, en sélectionnant un ou plusieurs utilisateurs, une ou plusieurs catégories.
    pour l'instant ça fonctionne, mais je trouve le code pas beau... et je cherche à le simplifier.

    Ma question, j'aimerai savoir si il y a un moyen de partir par exemple sur un context de base qui retourne par défaut la totalité, et mettre une condition si j'ai un utilisateur ou plusieurs de sélectionné, tu ajoutes une clause where, même chose pour la catégorie si j'en trouve une ou plusieurs.

    voici mon code actuel :

    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    public static List<MDAOffice_Logs> GetLogList(string _SelectedUsers = null, string _SelectedCategories = null)
    {
        if (_SelectedUsers == null && _SelectedCategories == null)
        {
        // On affiche tout le log  
          using (var context = new MDAOfficeEntities())
          {
              return context.MDAOffice_Logs.Include("Admin_Users")
                     .OrderByDescending(o => o.DateLog).ThenByDescending(o => o.HeureLog)
                     .ToList();
          }
        }
        else if (_SelectedUsers != null && _SelectedCategories == null)
        {
        // On affiche les entrées pour un ou plusieurs utilisateurs de sélectionnés 
          int[] findUser = _SelectedUsers.Split(',').Select(int.Parse).ToArray();
          using (var context = new MDAOfficeEntities())
          {
              return context.MDAOffice_Logs.Include("Admin_Users")
                     .Where(f => findUser.Any(s => f.Id_User.Equals(s)))
                     .OrderByDescending(o => o.DateLog).ThenByDescending(o => o.HeureLog)
                     .ToList();
          }
        }
        else if (_SelectedUsers != null && _SelectedCategories != null && _DateOperationFilter == null)
        {
        // On affiche un ou plusieurs utilisateurs et une ou plusieurs catégories de sélectionnées 
          int[] findUser = _SelectedUsers.Split(',').Select(int.Parse).ToArray();
          string[] findCategorie = _SelectedCategories.Split(';');
          using (var context = new MDAOfficeEntities())
            {
                return context.MDAOffice_Logs.Include("Admin_Users")
                       .Where(f => findCategorie.Any(s => f.Categorie.Contains(s)))
                       .Where(f => findUser.Any(s => f.Id_User.Equals(s)))
                       .OrderByDescending(o => o.DateLog).ThenByDescending(o => o.HeureLog)
                       .ToList();
            }
        }
        else if (_SelectedUsers == null && _SelectedCategories != null)
        {
        // On affiche les entrées pour une ou plusieurs catégories de sélectionnées 
          string[] findCategorie = _SelectedCategories.Split(';');
          using (var context = new MDAOfficeEntities())
          {
              return context.MDAOffice_Logs.Include("Admin_Users")
                     .Where(f => findCategorie.Any(s => f.Categorie.Contains(s)))
                     .OrderByDescending(o => o.DateLog).ThenByDescending(o => o.HeureLog)
                     .ToList();
          }
        }
        else
        {
          return null;
        }   
    }
    Le pire c'est que j'aimerai ajouté par la suite, la possibilité de filtrer sur les dates également, et si je pars sur mon code actuel, il va faire 300 km de long en testant toutes les possibilités.

    Merci pour votre aide.

    Alex

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Je pense que tu vas pas échapper aux conditions, vu que c'est justement conditionnelle!
    Par contre tu peux utiliser un mécanisme fondamental qu'utilise entityFramework : IQueryable.
    Si tu remarques bien tes appels EF sont chainables, parcequ'il retourne tous le meme type d'objet.
    Tu peux te créer tes propres méthode (en private surement) qui retournent elles aussi des IQueryable.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private IQueryable GetLogAdmin(DbContext context)
    {
     return context.MDAOffice_Logs.Include("Admin_Users").OrderByDescending(o => o.DateLog).ThenByDescending(o => o.HeureLog)
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private IQueryable AddFilterByUser(IQueryable query,string _SelectedUsers )
    {int[] findUser = _SelectedUsers.Split(',').Select(int.Parse).ToArray();
    return query.Where(f => findUser.Any(s => f.Id_User.Equals(s)));
    }
    Et ainsi de suite, ce qui te permet de réutiliser tes fonctions. Ta fonction principal sera bien plus allégée.

    ps:le code est pas testé du tout et ca fait un bout que j'ai pas touché à EF, ca mérite surement modifs mais l'idée est là.


    edit:
    Ce qui donne en gros une fonction comme ceci:
    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
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    public static List<MDAOffice_Logs> GetLogList(string _SelectedUsers = null, string _SelectedCategories = null)
    {
         var logAdmin=GetLogAdmin();
         using (var context = new MDAOfficeEntities())
          {
        if (_SelectedUsers == null && _SelectedCategories == null)
        {
         // On affiche tout le log  
         return logAdmin.ToList(); 
        }
        else if (_SelectedUsers != null && _SelectedCategories == null)
        {
            // On affiche les entrées pour un ou plusieurs utilisateurs de sélectionnés 
              return  logAdmin.AddFilterByUser(IQueryable query,string _SelectedUsers).ToList();
     
        }
        else if (_SelectedUsers != null && _SelectedCategories != null && _DateOperationFilter == null)
        {
        // On affiche un ou plusieurs utilisateurs et une ou plusieurs catégories de sélectionnées 
         return  logAdmin.AddFilterByUser(IQueryable query,string _SelectedUsers).AddAutreFiltre(...).ToList();
        }
        else if (_SelectedUsers == null && _SelectedCategories != null)
        {
        // On affiche les entrées pour une ou plusieurs catégories de sélectionnées 
        .......
        }
        else
        {
          return null;
        }   
     }
    }

  3. #3
    Membre expert
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2013
    Messages
    1 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2013
    Messages : 1 563
    Points : 3 404
    Points
    3 404
    Par défaut
    Citation Envoyé par Poulki Voir le message
    Ma question, j'aimerai savoir si il y a un moyen de partir par exemple sur un context de base qui retourne par défaut la totalité, et mettre une condition si j'ai un utilisateur ou plusieurs de sélectionné, tu ajoutes une clause where, même chose pour la catégorie si j'en trouve une ou plusieurs.
    Pour moi, ta première condition n'a pas réellement lieu d'être. Ton contexte par défaut est "tous les utilisateurs sont sélectionnés". Dans ce cas, tu de devrais jamais avoir _selectedUsers == null. De même pour les dates.

    Autrement dit, plutôt que de récupérer directement "string _SelectedUsers = null, string _SelectedCategories = null", tu devrais récupérer un filtre contenant ces valeurs retravaillées de manière à avoir du sens.

  4. #4
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Effectivement utiliser IQueryable<T> avec Lazy Loading est une bonne solution.

    Attention cependant, dans une application Web MVC/WebAPI il est deconseille d'utiliser le Lazy Loading car on peut rapidement arriver a lancer x fois plus de requetes SQL que necessaire si on ne sait pas ce que l'on fait.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  5. #5
    Nouveau membre du Club
    Inscrit en
    Juillet 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Juillet 2007
    Messages : 42
    Points : 33
    Points
    33
    Par défaut
    Merci pour votre aide,

    J'essaie la solution de Micka132 mais le code n'a pas l'air de jouer.

    Pour la partie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    private IQueryable GetLogAdmin(DbContext context)
            {
                return context.MDAOffice_Logs.Include("Admin_Users").OrderByDescending(o => o.DateLog).ThenByDescending(o => o.HeureLog);
    
            }
    Il me dit "DbContext ne contient pas de définition pour MDAOffice_Logs et aucune méthode d'extension 'MDAOffice_Logs' acceptant un premier argument de type 'DbContext' n'a été trouvée"


    pour la partie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    private IQueryable AddFilterByUser(IQueryable query, string _SelectedUsers)
            {
                int[] findUser = _SelectedUsers.Split(',').Select(int.Parse).ToArray();
                return query.Where(f => findUser.Any(s => f.Id_User.Equals(s)));
            }
    Il me dit "IQueriable ne contient pas de définition pour Where et aucune méthode d'extension 'Where' acceptant un premier argument de type 'IQueriable' n'a été trouvée

    et pour terminer, cette partie :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     {
                var logAdmin = GetLogAdmin();
                using (var context = new MDAOfficeEntities())
                {
                    
                    if (_SelectedUsers == null && _SelectedCategories == null)
                    {
                        // On affiche tout le log  
                        return logAdmin.ToList();
                    }
                }
    J'ai "Parmi les arguments spécifiés, aucun ne correspond au paramètre formel et obligatoire 'context' de 'MDAOfficeLogData.GetLogAdmin(DbContext)"

    Je suis perdu !

  6. #6
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Utilise "MDAOfficeEntities context" au lieu de "DbContext context".

    Déplace getLogAdmin à l'interieur, et rajoutes context en paramètre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
                using (var context = new MDAOfficeEntities())
                {
    var logAdmin = GetLogAdmin(context);
    ....
    }
    Pour le Where je ne sais pas trop, désolé j'ai peu de temps actuellement, mais c'est peut etre parcequ'il n'existe qu'en générique (IQueryable<T>) comme le souligne DotNetMatt

  7. #7
    Nouveau membre du Club
    Inscrit en
    Juillet 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Juillet 2007
    Messages : 42
    Points : 33
    Points
    33
    Par défaut
    merci, effectivement il y a moins d'erreur, par-contre il n'aime pas le

    Il me dit "IQueriable ne contient pas de définition pour 'ToList' et aucune méthode d'extension 'ToList' acceptant un premier argument de type 'IQueriable' n'a été trouvée

  8. #8
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Citation Envoyé par Poulki Voir le message
    Il me dit "IQueriable ne contient pas de définition pour 'ToList' et aucune méthode d'extension 'ToList' acceptant un premier argument de type 'IQueriable' n'a été trouvée
    A la place de IQueryable, remplace par IQueryable<MDAOffice_Log>

  9. #9
    Nouveau membre du Club
    Inscrit en
    Juillet 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Juillet 2007
    Messages : 42
    Points : 33
    Points
    33
    Par défaut
    Yes, ça fonctionne pour une liste sans filtre. Merci.

    Par-contre si t'as une solution pour l'histoire du .Where qui veut pas, je suis preneur ;-)

    Merci pour ta précieuse aide.

  10. #10
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Citation Envoyé par Poulki Voir le message
    Par-contre si t'as une solution pour l'histoire du .Where qui veut pas, je suis preneur ;-)
    Faut lui demander gentiment !

    Ou sinon, est-ce que tu as bien remplacé partout le IQueryable? Notamment sur les fonctions de filtres ca devient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    private IQueryable<MDAOffice_Log>  AddFilterByUser(IQueryable<MDAOffice_Log>  query,string _SelectedUsers )
    {int[] findUser = _SelectedUsers.Split(',').Select(int.Parse).ToArray();
    return query.Where(f => findUser.Any(s => f.Id_User.Equals(s)));
    }

  11. #11
    Nouveau membre du Club
    Inscrit en
    Juillet 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Juillet 2007
    Messages : 42
    Points : 33
    Points
    33
    Par défaut
    Oui j'avais modifié entre temps, et maintenant (ça avance) il n'aime pas le return :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return logAdmin.AddFilterByUser(IQueryable query, string _SelectedUsers).ToList();
    - ne contient pas de définition pour MDAOffice_Logs et aucune méthode d'extension 'AddFilterByUser' acceptant un premier argument de type 'IQueryable<MDAOffice_Log>' n'a été trouvée"
    - IQueryable est un type, qui n'est pas valide dans le contexte donné
    - query n'existe pas dans le contexte actuel
    - terme d'expression 'string' non valide
    - _SelectedUsers Erreur de syntaxe, ',' attendu

    J'ai essayé de modifier comme ceci, étant donné qu'il ne connait pas 'query' :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return logAdmin.AddFilterByUser(IQueryable<MDAOffice_Logs> logAdmin, _SelectedUsers).ToList();
    Qui donne un peu moins d'erreurs, mais il veut pas.

  12. #12
    Expert confirmé
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Novembre 2009
    Messages
    2 025
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Novembre 2009
    Messages : 2 025
    Points : 5 462
    Points
    5 462
    Par défaut
    Citation Envoyé par Poulki Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return logAdmin.AddFilterByUser(IQueryable<MDAOffice_Logs> logAdmin, _SelectedUsers).ToList();
    Là pour le coup tu fais un appel à une fonction, donc il n'y a pas à spécifier le type, il ne faut donc pas du tout spécifier le IQueryable, ni le string (sauf si tu dois faire un cast, ce qui n'est pas le cas ici, ni la bonne syntaxe ).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return AddFilterByUser(logAdmin, _SelectedUsers).ToList();
    Désolé pour le premier jet de mon code bourré d'erreur

    edit:
    par contre pour plus de filtre ca devient

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AddAutreFiltre(AddFilterByUser(logAdmin, _SelectedUsers)).ToList();
    Initialement je penser à "chainer" les instructions mais ca fait intervenir la notion d'extension de classe (https://docs.microsoft.com/fr-fr/dot...ension-methods). Déjà essaye simple si ca fonctionne

  13. #13
    Nouveau membre du Club
    Inscrit en
    Juillet 2007
    Messages
    42
    Détails du profil
    Informations personnelles :
    Âge : 53

    Informations forums :
    Inscription : Juillet 2007
    Messages : 42
    Points : 33
    Points
    33
    Par défaut
    Excellent ! un grand merci pour ta patience, ça fonctionne à merveille !
    Je passe l'affaire en résolu

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 17/10/2013, 15h01
  2. Réponses: 3
    Dernier message: 22/07/2009, 12h04
  3. Est-il possible de faire des classes autoinstanciées ?
    Par All Jinx dans le forum Débuter
    Réponses: 7
    Dernier message: 22/08/2008, 17h36

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