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

Windows Forms Discussion :

Effectuer une requête SQL multiple paramétrée ?


Sujet :

Windows Forms

  1. #1
    Membre du Club Avatar de mathisdu42
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2013
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2013
    Messages : 168
    Points : 64
    Points
    64
    Par défaut Effectuer une requête SQL multiple paramétrée ?
    Bonjour, bonsoir à tous.

    Comme l'indique le titre, j'essaie d'établir une requête sql paramétrée multiple mais je rencontre quelques difficultés. Mon but principal est le suivant :
    Récupérer les notes (d'un étudiant) et les dates (des devoirs) en fonction du semestre (1 ou 2) du nom d'utilisateur et de la matière le tout affiché sous la matière correspondante. (Et par la suite, avec des COUNT, calculer la moyenne élève + classe)
    (Exemple : L'étudiant Paul se connecte à l'application. Il souhaite voir ses notes, il clique donc sur le bouton "Voir mes notes". Se présente alors ses 8 matières sous lesquelles sont affichées toutes ses notes. Sous la matière Programmation, Paul peut voir qu'il a eu deux notes, sous la matière Économie & Droit, il n'en a pas eu.)

    Précision : J'ai crée deux UserControl. L'un possédant les 8 matières et le second qui sera dupliqué en fonction du nombre de notes et dans lequel sera stocké la date et la note du contrôle :

    UserControl1 (ControlDetailsNotes) :

    Nom : u1.png
Affichages : 418
Taille : 3,4 Ko

    UserControl2 (ControlDetailsNotes2):

    Nom : u2.png
Affichages : 425
Taille : 1,5 Ko

    J'ai donc, pour plus de clarté, créer une bibliothèque de classe dans laquelle j'ai structuré mon code de cette manière :

    - Dans un premier temps, je créer ma méthode publique statique GetNote();.
    - Ensuite, je déclare dans une variable string mes requêtes, dans une seconde variable je déclare ma connexion, puis une troisième ma commande.
    - J'initialise les deux variables (requête, connexion)
    - J'ouvre ma connexion puis fais mes paramètres (en l’occurrence, mes paramètres sont les 8 matières, le semestre ainsi que le nom de l'élève).
    - Je crée une variable de type int que j'initialise à 0 (permettra la création multiple d'un UserControl)
    - Crée une variable reader assignée à un ExecuteReader();
    - Et enfin, je fais une boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    while(reader.Read())
    {
    ...
    }
    puis un - Dans un second temps, je crée une seconde méthode nommée dans la quelle je mets le code de récupération des données (Dates + Notes) et de création de l'UserControl.

    Code :

    Méthode principale : (J'ai raccourci le code à 2 matières pour l'explication)

    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
    public static void GetNotes(Panel pn1, Panel pn2, string user) // Ces paramètres (pn1, pn2 correspondent au nombre de matières
                                                                                               // UserControl2 (ControlDetailsNotes2) sera placé dans des panels sous toutes les matières
            {
     
                string commandText = @"SELECT Note, Date FROM Notes WHERE Semestre=@semestre AND Eleve=@eleve AND Matiere=@m1;
                SELECT Note, Date FROM Notes WHERE Semestre=@semestre AND Eleve=@eleve AND Matiere=@m2;";
     
     
                using (MySqlConnection dbConnection = new MySqlConnection(@"server=mysql-****.always****.net;Port=3306; userid=****; password=****; database=**_bdd;"))
                using (MySqlCommand dbCommand = new MySqlCommand(commandText, dbConnection))
                {
                    dbCommand.CommandType = CommandType.Text;
                    dbConnection.Open();
     
                    // Les paramètres : Le but est de récupérer les Dates des devoirs et Notes des devoirs pour toutes les matières et pour l'user connecté
     
                    dbCommand.Parameters.Add(new MySqlParameter("@m1", MySqlDbType.VarChar));
                    dbCommand.Parameters["@m1"].Value = "Programmation";
                    dbCommand.Parameters.Add(new MySqlParameter("@m2", MySqlDbType.VarChar));
                    dbCommand.Parameters["@m2"].Value = "Économie et Droit";
     
                    dbCommand.Parameters.Add(new MySqlParameter("@semestre", MySqlDbType.VarChar));
                    dbCommand.Parameters["@semestre"].Value = "1";
                    dbCommand.Parameters.Add(new MySqlParameter("@eleve", MySqlDbType.VarChar));
                    dbCommand.Parameters["@eleve"].Value = user; //Je récupère le nom d'utilisateur
     
                    //Cette variable sert à dupliquer UserControl2 (notes + dates) tant qu'il y a des notes
                    int cptr = 0;
     
                    var reader = dbCommand.ExecuteReader();
     
                    // Logiquement : Tant que le programme lira des données, il créera ControlDetailsNotes2 (UserControl2) tant qu'il y aura des données 
                    while (reader.Read())
                    {
                         ReaderRead(reader, -1, 3, cptr, 52, pn1);  // -1,3 : Position du Contrôle Utilisateur | (cptr++ * 52) : Espaces entre les contrôles utilisateurs
                    }
     
                    reader.NextResult();
     
                    while (reader.Read())
                    {
                         ReaderRead(reader, -1, 3, cptr, 52, pn1);
                    }
                }
            }
    Méthode ReaderRead :

    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
    private static void ReaderRead(MySqlDataReader reader, int x, int y, int cptr, int multp, Panel tm)
            {
                DateTime dt;
                ControlDetailsNotes2 ccc = new ControlDetailsNotes2();
                dt = reader.GetDateTime("Date");
                Math.Round(Convert.ToDecimal(ccc.LblNoteControleM.Text = reader.GetDouble("Note").ToString()), 2);
                ccc.Location = new Point(x, y + (cptr++ * multp));
                ccc.LblDateM.Text = "le " + dt.ToString("dd/MM");
     
                if (Convert.ToDecimal(ccc.LblNoteControleM.Text) < 10)
                {
                    ccc.LblNoteControleM.ForeColor = Color.DarkRed;
                }
                else if (Convert.ToDecimal(ccc.LblNoteControleM.Text) > 11)
                {
                    ccc.LblNoteControleM.ForeColor = Color.Green;
                }
     
                 //pn correspond à la matière (Ex : pn1 : Programmation) - (pn2 : Économie & Droit)
                pn.Controls.Add(ccc);
            }

    Et enfin, le code pour accéder à la bibliothèque :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    [...].Notes.GetNotes(panelControlDN1, panelControlDN2, panelControlDN3, panelControlDN4, panelControlDN5, panelControlDN6,panelControlDN7,panelControlDN8, lblInfosUser.Text);
    Hélas, le résultat n'est pas concluant. En effet, quand je test, au lieu d'avoir deux notes dans la matière "Programmation", j'obtiens seulement une note avec la date. Cette note correspond à la première matière de la requête :

    Nom : err.png
Affichages : 466
Taille : 4,2 Ko

    Désolé d'avance pour la longueur du post et le code qui peut sembler brouillon.

    Merci,
    Cordialement.

  2. #2
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    plusieurs choses :
    - les détails c'est bien, mais là ca me parait un peu long (d'un autre côté ca permet de parler du reste de ton code)
    -
    SELECT Note, Date FROM Notes WHERE Semestre=@semestre AND Eleve=@eleve AND Matiere=@m1;
    SELECT Note, Date FROM Notes WHERE Semestre=@semestre AND Eleve=@eleve AND Matiere=@m2

    ca serait pas plus simple de faire
    SELECT Note, Date, Matiere FROM Notes WHERE Semestre=@semestre AND Eleve=@eleve AND Matiere IN (@m1, @m2) ORDER BY Matiere, Date
    ?
    ca évite d'avoir le nextresult et de faire 2 exécutions (perfs)
    (et à mon avis mettre les matières en paramètres n'est pas utile, je pense que tu les veux toute au final, que c'est juste dans quel uc ca va, et les uc peuvent être créé ou adressés à l'exécution)


    - normalement on découple un peu tout pour avoir du code générique et du code propre
    donc une méthode qui va lire des données sql et modifier des controles on évite
    niveau découpage il faudrait plutôt une classe d'accès aux données qui demande la requete et les paramètres (nom + type + value)
    => cette classe pourra être utilisée partout dans l'appli (elle peut retourner le datareader par exemple, ou un datatable ou autre)
    le getnotes utiliserait cette classe pour remplir un list<note> (matiere + date + note)
    le form/usercontrol qui aurait besoin de ces données appelerait GetNotes et récupèrerait une collection, lui s'occupera de modifier l'UI en fonction des données
    le but de tout ca c'est un débuggage plus simple (on peut tester chaque partie indépendamment), plus de lisibilité (quand on revient 6 mois après sur un code on ne se rappelle pas de tout), et ca amène aussi plus d'évolutivité (si tu veux changer un peu l'interface tu n'as pas à modifier du code de partout, juste une partie)

    une fois la liste List<note> récupérée tu peux faire un foreach group by matiere order by date en c# ca te permettra de bien remplir les controles sans trop de code

    - pour éviter de définir les x et y des controles qui sont des listes de chose on peut utiliser le flowlayoutpanel qui s'occupe de placer les controles les uns à la suite des autres dans la direction voulue
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 757
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 757
    Points : 10 697
    Points
    10 697
    Billets dans le blog
    21
    Par défaut
    Bonjour,

    Je pense que le problème est que les deux notes sont affichées aux mêmes coordonnées.

    Si j'ai bien compris le principe du code, il faut modifier légèrement la signature de la méthode
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    private static void ReaderRead(MySqlDataReader reader, int x, int y, ref int cptr, int multp, Panel tm)

    Il faut rajouter le mot clé ref pour la variable cptr, puisque la méthode doit mettre à jour la variable cptr. Sans cela, la valeur de la variable n'est pas modifiée en dehors de la fonction (car passée par valeur et non par référence).
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

  4. #4
    Membre du Club Avatar de mathisdu42
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2013
    Messages
    168
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2013
    Messages : 168
    Points : 64
    Points
    64
    Par défaut
    Merci à tous les deux pour vos réponses.

    Pour la pratique, la méthode de François DORIN fonctionnait très bien mais avec l'utilisation des panels c'était vachement pas propre (Problème de positionnement).
    Du coup j'ai opté, comme conseillé, d'utiliser le contrôle FlowLayoutPanel. Pour le moment j'ai pas beaucoup modifié mon code, simplement remplacé les panels.
    Je laisse comme ça provisoirement. En attendant je vais étudier et tenter de mettre en place les conseils que tu m'as donné (Pol63) puisque effectivement,
    du point de vue perfs, faire 8 exécutions c'est pas vraiment conseillé. (C'est pas en 1ère année SIO qu'on apprend le découplage ahah)

    Tout conseil est bon à prendre.
    Merci.

Discussions similaires

  1. [SQL Serveur] Effectuer une requête SQL en Perl
    Par benji1000 dans le forum SGBD
    Réponses: 7
    Dernier message: 19/12/2012, 16h46
  2. Effectuer une requête SQL en Pascal
    Par zpliz dans le forum Pascal
    Réponses: 6
    Dernier message: 26/04/2010, 14h02
  3. Langage pour effectuer une requête SQL.
    Par slake13 dans le forum Langages de programmation
    Réponses: 3
    Dernier message: 19/11/2008, 13h22
  4. Réponses: 5
    Dernier message: 11/09/2007, 13h17
  5. Modification d'un paramètre d'une requête SQL
    Par Anto03 dans le forum Requêtes et SQL.
    Réponses: 8
    Dernier message: 21/12/2006, 16h01

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