Requete SQL ComboBox

Signaler
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010
-
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010
-
Voila , ma liste se charge bel et bien dans ma premiere combobox mais avc la condition dans la requete2 WHERE Pays='"+pays+"'; pas moyen d'obtenir les codes postaux mis en relation avec le pays tandis que sans cette condition tous les codes postaux se chargent sans difficulté.
J'ai éssayé diverse méthodes mais sans succès. Pourriez vous m'éclairer sur l'erreur ?
		    while(myReader.Read())
    {
    			cbPays.Items.Add(myReader["Pays"]);
    }
    string pays = (string)cbPays.SelectedItem;
    string requete2 = "SELECT Departement FROM Europe WHERE Pays='"+pays+"';";
    OleDbCommand command2 = new OleDbCommand(requete2, Calculette);
    OleDbDataReader myReader2;
    myReader2 = command2.ExecuteReader();
    while(myReader2.Read())
    {
    	cbCP.Items.Add(myReader2["Departement"]);
    }
    Calculette.Close();

31 réponses

Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
48
Salut

Tout d'abord, il n'était pas nécessaire de créer un nouveau post.

Ensuite, ton code tel quel ne risque pas de marcher, puisque tu crées ta deuxième requête tout de suite après avoir rempli la première cbox, donc avant que tu aies pu sélectionner une valeur.
Il te faut donc utiliser un événement (par exemple SelectedIndexChanged)

// Lors de la création de ta form : 
cbPays.SelectedIndexChanged += new EventHandler(cbPays_SelectedIndexChanged);
// Connexion à la base, etc
while(myReader.Read())
{
    cbPays.Items.Add(myReader["Pays"]);
}



// Puis la fonction appelée lors du déclenchement de l'événement :
void cbPays_SelectedIndexChanged(object sender, EventArgs e)
{
    // Connexion à la base, etc
    string pays = (string)cbPays.SelectedItem;
    string requete2 = "SELECT Departement FROM Europe WHERE Pays='"+pays+"';";
    OleDbCommand command2 = new OleDbCommand(requete2, Calculette);
    OleDbDataReader myReader2;
    myReader2 = command2.ExecuteReader();
    while(myReader2.Read())
    {
    	cbCP.Items.Add(myReader2["Departement"]);
    }
    Calculette.Close();
}


Enfin, les bonnes pratiques conseillent d'utiliser des requêtes paramétrées :
// Au lieu de 
string requete2 = "SELECT Departement FROM Europe WHERE Pays='"+pays+"';";
OleDbCommand command2 = new OleDbCommand(requete2, Calculette);

// Il vaut mieux faire
string requete2 = "SELECT Departement FROM Europe WHERE Pays=@Pays;";
OleDbCommand command2 = new OleDbCommand(requete2, Calculette);
command2.Parameters.Add(new OleDbParameter("@Pays", pays));


Ce système rend ton code plus lisible, évite les injection SQL et te permet de ne pas avoir à te soucier du type de ta variable.
Que ce soit un bool, un int, un string, une date... tu utiliseras toujours
"WHERE MonChamp=@DuTexte" puis new OleDbParameter("@DuTexte", valeur);

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
39
Date d'inscription
lundi 10 novembre 2008
Statut
Membre
Dernière intervention
7 septembre 2010
1
Salut,
Tu devrais tester ta requête sql en affichant la variable "pays" dans la console juste pour voir si elle est bien correctement écrite.
Si t'a variable est erroné essaye de changer :
string pays = (string)cbPays.SelectedItem;

par
string pays = cbPays.SelectedItem.ToString;


Sinon essaye de tester ta requête sql directement dans ton SGBD pour voir elle retourne bien les enregistrement désirés.
Messages postés
39
Date d'inscription
lundi 10 novembre 2008
Statut
Membre
Dernière intervention
7 septembre 2010
1
MEA CULPA : krimog a raison !
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010

D'accord , désolé pour le nouveau post ^^', j'ai pas trop l'habitude d'utiliser un forum ^^.
Je ne connaissais pas du tout cet évènement , j'aurais pu chercher encore longtemps.
Merci beaucoup. J'ai rajouté un
cbCP.Items.Clear();
au début de cet évènement car dès qu'on changeait de pays il accumulé les codes postaux!

Encore merci, je te suis redevable :p
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
48
@Perecastorr : n'oublie pas () après ToString

Autre petite "bonne pratique" : utilise plutôt des identifiants que du texte pour tes recherches. Tu seras à l'abri des doublons et des problèmes de format (en cas d'accent ou de caractère spécial) et ce sera plus rapide.

krimog a raison !

J'adore cette phrase
Mais je suis trop modeste pour la marquer autre part que dans une citation xD

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010

Un truc par contre que je ne comprends pas du tout c'est du coup pour le changement de status d'un bouton radio j'ai utilisé le CheckedChanged en suivant ton exemple et c'est d'ailleurs grâce à toi que j'y ai penser.
Seul bémole c'est ce problème (sa doit être encore basique mais la résolution ne m'apparaît pas du tout)
void radioMPL_CheckedChanged(object sender, EventArgs e)
{
while(radioMPL.Checked==false)
{
cbMPL.Enabled==false;
}
}

Avec pour erreur

Seuls une assignation, un appel, un incrément, un décrément et des expressions d'objet new peuvent être utilisés comme instruction (CS0201)
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010

Débilité profonde de ma part.. le == remplacé par un = !

Veuillez m'excuser pour ce unbrained passage ;D
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
48
Euh, tu devrais remplacer ton while par un if. Sinon tu risques d'avoir des problèmes

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010

Je l'avais fais , mais merci :D
Petite pause pour manger , bonne appétit :)
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010

Alors voila , j'ai essayé de suivre ce que tu m'as dis..mais rien ne se passe quand je clique. A part un plantage ><

		void ButtonCalcClick(object sender, EventArgs e)
{
if(cbMPL.Enabled==false || cbPAL100120.Enabled==false || cbPAL80120.Enabled==false)
{
OleDbConnection Calculette = new OleDbConnection(connect);
   		Calculette.Open();
    string pays = (string)cbPays.SelectedItem;
    string dep = (string)cbCP.SelectedItem;
    double num =0;
    if(cbMPL.Enabled==true)
    {
    	num =(double)cbMPL.SelectedItem;
    }
    else if(cbPAL80120.Enabled==true)
    {
    	num = (double)cbPAL80120.SelectedItem;
    }
    else
    {
    	num = (double)cbPAL100120.SelectedItem;
    }
    string requete2 = "SELECT @num FROM Europe WHERE Pays=@Pays AND Departement=@Departement;";
OleDbCommand command2 = new OleDbCommand(requete2, Calculette);
command2.Parameters.Add(new OleDbParameter("@Pays", pays));
command2.Parameters.Add(new OleDbParameter("@Departement", dep));
command2.Parameters.Add(new OleDbParameter("@num", num));
    OleDbDataReader myReader2;
    myReader2 = command2.ExecuteReader();
    MessageBox.Show((string)myReader2["@num"]);
    Calculette.Close();
}
else
{
MessageBox.Show("Veuillez remplir les champs.");
}
}



Message d'erreur associé:

System.InvalidOperationException: Aucune donnée n'existe pour la ligne/colonne.
à System.Data.OleDb.OleDbDataReader.DoValueCheck(Int32 ordinal)
à System.Data.OleDb.OleDbDataReader.GetValue(Int32 ordinal)
à System.Data.OleDb.OleDbDataReader.get_Item(String name)
à ButtonCalcClick(Object sender, EventArgs e) dans à System.Windows.Forms.Control.OnClick(EventArgs e)
à System.Windows.Forms.Button.OnClick(EventArgs e)
à System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
à System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
à System.Windows.Forms.Control.WndProc(Message& m)
à System.Windows.Forms.ButtonBase.WndProc(Message& m)
à System.Windows.Forms.Button.WndProc(Message& m)
à System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
à System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
à System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Je pense que cette expérience va me faire ressortir bien plus riche en C# que quand j'ai commencé ^^"
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
48
N'utilise pas de paramètre pour tes champs de retour :

"SELECT num FROM Europe WHERE Pays=@Pays AND Departement=@Departement;";
(si tu as bien un champ num dans ta table Europe)

(efface la ligne command2.Parameters.Add(new OleDbParameter("@num", num));)

MessageBox.Show((string)myReader2["num"]);


Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010

JE n'ai pas de champ num en faite j'ai 0.5 1 1.5 etc jusque 13.5 et en fonction de ce qu'a choisis l'utilisateur dans la combobox sa va me chercher la donnée a cette endroit. C'est un peu la galere , j'avais eu l'idée du coup de faire ce que tu as écris mais il y a un probleme..il recupere un double dans myReader et il me dit que c'est impossible il lui faut un int !
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010

J'ai passé 2heures hier sans succès..toujours ce probleme de double avec myReaer et je ne connais aucune alternative à sa ^^'.
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
48
Je crois que tu n'as pas bien compris ce que j'ai voulu dire en parlant d'identifiant : je parlais dans tes tables.

Exemple :
table Pays(Id, Nom, Population)
table Ville(Id, Nom, CodePostal, IdDepartement)
table Departement(Id, Nom, Code, IdPays)

Valeurs pour l'exemple :
Pays : (3, France, 60 000 000)
Ville : (58, Caen, 14000, 14), (713, Ile Rousse, 20220, 21)
Departement : (14, Calvados, 14, 3), (21, Haute Corse, 2B, 3)

Et normalement, tu demandes à ta base d'incrémenter automatiquement l'identifiant pour chaque nouvel enregistrement (Identitée en SQL Server, Auto_Increment en MySQL...)
Et dans tes select, tu n'utilises (tant que possible) que les identifiants

Pour connaitre le nom et la population du pays 3
SELECT Nom, Population FROM Pays WHERE Id = 3;


Pour connaitre le nom et l'identifiant du pays dans lequel se trouve la ville 70
SELECT Pays.Nom, Pays.Id
FROM Pays
INNER JOIN Departement ON Pays.Id = Departement.IdPays
INNER JOIN Ville ON Departement.Id = Ville.IdDepartement
WHERE Ville.Id = 70;


Et j'avoue en fait ne pas bien comprendre ta requête SQL :
SELECT num FROM Europe WHERE Pays=@Pays AND Departement=@Departement;

Ce qui signifie "Je récupère le champ num des enregistrements de la table Europe dont le champ Pays vaut @Pays et Departement vaut @Departement"
Déjà, ta table Europe, je ne vois pas ce à quoi elle correspond. Une table est un ENSEMBLE de valeurs. Pour moi l'Europe est unique. "Continent" serait un meilleur nom (si tant est qu'il s'agisse bien de ça).
De plus, tu fais une condition sur Pays et sur Departement. Tu n'utilises qu'une table. Donc ça signifie que Pays et Departement sont des champs de la même table (en l'occurrence Europe). Pour moi, un département est dans un pays et un pays contient plusieurs départements. Donc si tu précise le département, logiquement, c'est censé préciser automatiquement le pays.

Donc ton problème est avant tout un problème de conception. Si tu ne comprends pas le problème, explique exactement ce que tu cherches à faire avec ta requête et indique-moi la structure de ta base de données.

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010

Alors voila, dans ma table Europe, j'ai un Numero en Autoincrement (pour une clé primaire) j'ai des Pays et tous les departement lié à ces pays par exemple pour GB (Grande Bretagne) j'ai :

1 GB AB
2 GB AL
3 GB B

etc etc...
En plus de sa j'ai des colonnes 1 1.5 2 2.5 jusque 13 comprenant des prix. ce qui nous donne

Numéro|Pays|Département|1..|1.5|2..|2.5|etc
1.....|GB..|AB.........|648|648|756|810|etc

Ma combo box mes combobox me permette de choisir ce chiffres variable au besoin de l'utilisateur 1 1.5 2 etc
pour allez chercher le prix correspondant au pays avec le département sur cette meme ligne.

Je ne sais pas si j'ai été claire.
Après modification j'ai une erreur comme quoi ma colonne n'existe pas ! Je te colle le code :

 if(cbMPL.Enabled==true)
    {
    	num =(double)cbMPL.SelectedItem;
    }
    else if(cbPAL80120.Enabled==true)
    {
    	num = (double)cbPAL80120.SelectedItem;
    }
    else
    {
    	num = (double)cbPAL100120.SelectedItem;
    }
    string requete3 = "SELECT "+num+" FROM Europe WHERE Pays=@Pays AND Departement=@Departement;";
OleDbCommand command3 = new OleDbCommand(requete3, Calculette);
command3.Parameters.Add(new OleDbParameter("@Pays", pays));
command3.Parameters.Add(new OleDbParameter("@Departement", dep));
    OleDbDataReader myReader3;
    myReader3 = command3.ExecuteReader();
    double tarifs=(double)myReader3[(int)num];
    Calculette.Close();
    MessageBox.Show(tarifs+"");


J'ai fais un MessageBox.Show(num)avant la requete SQL et il m'indique bien le numéro selectionné. Mais apres la requete il me dit que celle ci n'éxiste pas ^^.
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
48
Alors je crois avoir compris d'où vient ton problème : tu ne peux pas appeler une colonne 1.5 ou 2...

Théoriquement, ça doit forcément commencer par une lettre et ne contenir aucun symbole spécial sauf _

Donc tu peux les appeler "Colonne1", "Colonne1_5", "Colonne2"...

De plus, dans ton code (si on fait abstraction du problème ci-dessus),
myReader3[(int)num];

est incorrect. Ce que tu cherches, ce n'est pas la valeur de la colonne d'indice num, mais la valeur de la colonne NOMMEE num. Donc il faut lui fournir un string.

myReader3[num.ToString()];



Donc pour corriger ça, essaie de renommer tes colonnes dans ta BDD comme indiqué ci-dessus, et
// Remplace
num
// Par
"Colonne" + num.ToString().Replace(",", "_").Replace(".", "_");
// Je replace également les virgules car je crois que ToString()
// doit utiliser une virgule à la place d'un point.


Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010

Hum effectivement il détecte les colonne maintenant mais me présente un outofrange.
Pourtant j'essaye en choisissant 1 dans ma combobox qui donc se refere à Colonne1 dans la bdd.
Et beh..pour ma première utilisation des bases de données sous C# je suis gaté...
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
48
A quelle ligne te fait-il ton exception ?

PS : normalement, on ne fait pas ce type de filtrage sur les colonnes, c'est ça qui complique le truc.

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -
Messages postés
22
Date d'inscription
mardi 31 mars 2009
Statut
Membre
Dernière intervention
8 janvier 2010

Ok lol j'ai voulu faire un truc qu'on ne fait pas habituellement si j'ai bien compris xD.
Sur:
double tarifs=(double)myReader3["Colonne" + num.ToString().Replace(",", "_").Replace(".", "_")];


Encore merci en tous cas de donner de ton temps pour moi.
Messages postés
1860
Date d'inscription
lundi 28 novembre 2005
Statut
Modérateur
Dernière intervention
14 février 2015
48
Oublie pas myReader3.Read(); avant

Krimog : while (!(succeed = try())) ;
- Nous ne sommes pas des décodeurs ambulants. Le style SMS est prohibé. -