Probleme de boucle sur tableau d'objects...

Signaler
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008
-
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
-
B'jour b'jour !
alors voilà j'ai un souci...j'ai un tableau d'object à 2 dimensions qui reçoit le résultat d'une fonction exécutant une requête SQL...mon prbleme c'est que ma requête doit être dans un boucle mais sauvée dans sa totalité dans un tableau, la voici :

SELECT DQ.MSG_ID, DQ.USER_DATA_” + i + “,


ENQ_TIME, FINAL_TIME, MSG_STATE,


FAILURE_CODE, FAILURE_COMMENT


FROM DXCNT_QUEUE DQ


WHERE DQ.QUEUE = // sélectionnée depuis une listeBox


AND DQ.USER_DATA_” + i + “ IS NOT NULL


AND DQ.MSG_STATE = <code_statut> // variable initialisée au préalable


ORDER BY MSG_ID

vous remarquez certainement le "i" dans la requête: en fait, en abse, il y'a 10 champs USER_DATA_i, avec i de 0 à 9...j'ai donc voulu mettre cette requête dans une boucle...Donc, mon tableau reçoit le résultat de cette requete...sauf qu'évidemment, faire

for (int i=0; i<10; i++)
Result = connex.getquery("SELECT... ...")

ça va m'écraser Result à chaque tour....
j'ai donc pensé à faire

Result = Result + connex.getquery("SELECT ... ...")

mais Visual Studio me dit qu'on ne peut pas applioquer l'opérateur + sur un tableau d'objets....

donc voilà si quelqu'un pouvait m'aider à résoudre ça....merciii :)

"Un seul Être vous manque, et tout est dépeuplé..."

67 réponses

Messages postés
2368
Date d'inscription
mardi 17 avril 2001
Statut
Modérateur
Dernière intervention
26 décembre 2007
20
Pourquoi passer par des tableaux ??
DataSet / DataTables non ?

::|The S@ib|::
MVP C#.NET
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008

bah parce que ma fontion retourne un tableau et que j'sais pas m'servir des dataset etc...c un truc tout simple...et surtout paske j'ai pu vraiment l'temps d'apprendre :s:s

"Un seul Être vous manque, et tout est dépeuplé..."
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
36
salut, c'est peut etre un "tableau de tableaux" dont tu as besoin, c'est a dire un tableau ou chaque element est une reference a un autre tableau.
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008

hmm ca devient pas trop compliqué pour un truc si simple...?
et je vois pas vraiment ce que tu veux m'dire en fait :s
y'aurait un tableau contenant un résultat pour chaque i dans chaque case d'un tableau ?

"Un seul Être vous manque, et tout est dépeuplé..."
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
36
Tu dis que ta fonction renvoie un tableau, donc dans ta boucle elle va renvoyer 10 tableaux..c'est a dire 10 references de la classe Array.. faut bien les sauvegarder qlq part.. non ?
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008

un truc du genre
ResultFinal[i] = Result
a la fin de la bvoucle donc...?

"Un seul Être vous manque, et tout est dépeuplé..."
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
36
On peut aussi utiliser une collection ou juste un tableau de classe "Array", bien sur il faut que ta methode connex.getquery renvoie un tableau..

Array[ ] tab = new Array[ 10 ];

for ( int i = 0; i < 10; i++ )
{
tab[ i ] = connex.GetQuery( );
}
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008

y'a un truc que j'me demande....par exemple, disons que USER_DATA est renseigné jusqu'à 3
ma requête va remplir le tableau avec des doublons nan ? jveux dire y'aura dans la case 0 le msg_id, etc..., le user_data_0, puis dans la case 1, y'aura les memes msg_id etc...mais avec user_data_1...et comme j'ajoute le tout dans une DataGrid, ca va m'mettre des lignes en double j'imagine...?

Merci pour ton aide entous cas ;)

"Un seul Être vous manque, et tout est dépeuplé..."
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
36
Là faut attendre le retour de TheSaib, parce que moi SQL c'est pas mon truc.. J'ai juste percuté quand j'ai vu que tu voulais additionner des tableaux..
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008

lol j'te remercie en tous cas j'vais voir ce que ca donne, et au pire j'ferais de la manip' pour concaténer l'tout...merci bien c'est sympa

"Un seul Être vous manque, et tout est dépeuplé..."
Messages postés
2368
Date d'inscription
mardi 17 avril 2001
Statut
Modérateur
Dernière intervention
26 décembre 2007
20
Rajoute un distinct

SELECT DISTINCT DQ.Msg_id ....

::|The S@ib|::
MVP C#.NET
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008

OHHH QUEL HOMME...mdr
putain j'suis vraiment une croute de boeuf fossilisé desfois...lol merci...c'était évident en fait...pff jsuis trop bête lol
oki bah j'teste ça et j'viens accepter les réponses avec d modif eventuelles de ma part ;) thanks!

"Un seul Être vous manque, et tout est dépeuplé..."
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008

Bon...bah en fait j'y arrive pas...lol voilà le bout de code qui m'pose tant d'problème, je ne vois pas comment m'en sortir avec les tableaux...est-ce que quelq'un a une idée...?

Result = connex.getQueryResult("SELECT DISTINCT DQ.MSG_ID, DQ.ENQ_TIME, DQ.FINAL_TIME, DQ.MSG_STATE, DQ.FAILURE_CODE, DQ.FAILURE_COMMENT, DQ.USER_DATA_0 " +


"FROM DXCNT_QUEUE DQ " +


"WHERE DQ.USER_DATA_0 IS NOT NULL " +


"AND DQ.MSG_STATE = " + state +


" AND DQ.QUEUE = '" + ListBox_Interfaces.SelectedItem.ToString() + "' "+


"ORDER BY MSG_ID");


if (Result.GetLength(0) > 20)


{



for (
int i=0; i<20 ; i++)


{


DataRow row = dtaSet.Tables["MESSAGE"].NewRow();


row["MSG_ID"] = Result[i,0];


row["ENQ_TIME"] = Result[i,1];


row["FINAL_TIME"] = Result[i,2];


row["MSG_STATE"] = Result[i,3];


row["FAILURE_CODE"] = Result[i,4];


row["FAILURE_COMMENT"] = Result[i,5];


row["USER_DATA_0"] = Result[i,6].ToString().Substring(0,128);



// ajout de la ligne au Datagrid et rafraîchissement de celui-ci


dtaSet.Tables["MESSAGE"].Rows.Add(row);


DtaGrid_Result.Refresh();


}


}



else


{



for (
int i=0; i < Result.GetLength(0); i++)


{


DataRow row = dtaSet.Tables["MESSAGE"].NewRow();


row["MSG_ID"] = Result[i,0];


row["ENQ_TIME"] = Result[i,1];


row["FINAL_TIME"] = Result[i,2];


row["MSG_STATE"] = Result[i,3];


row["FAILURE_CODE"] = Result[i,4];


row["FAILURE_COMMENT"] = Result[i,5];


row["USER_DATA_0"] = Result[i,6].ToString().Substring(0,128);



// ajout de la ligne au Datagrid et rafraîchissement de celui-ci


dtaSet.Tables["MESSAGE"].Rows.Add(row);


DtaGrid_Result.Refresh();


}


}

"Un seul Être vous manque, et tout est dépeuplé..."
Messages postés
305
Date d'inscription
lundi 7 janvier 2002
Statut
Membre
Dernière intervention
10 août 2011
5
Heuuuu... juste une petite idée comme ça... plutôt que de faire un
tableau de tableaux, tu peux pas faire un tableau de RecordSets ?



Et même une collection, comme ça, tu te fais moins chier :



private Collection<Recordset> records = new Collection<Recordset>();

for(int i = 1; i < 10; i++){

Recordset rec = connex.getquery("SELECT... ...");

records.Add(rec);

}



après t'as plus qu'à traiter tes résultats comme ça :



foreach(Recordset r in records){

[...]

}
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008

Salut yoannd, merci de m'aider ! alors, ton idée me parait 'achement bien, mais mon cerveau ignore un peu comment ça marche...tu pourrais m'aider si je te file peut-être plus de code ou pas ? en fait je sais pas comment marchent les recordsets, les collections etc...et j'utilise un tableau d'Object[,] 2D parce que bah euh j'ai essayé et pi ça a marché quoi...lol

"Un seul Être vous manque, et tout est dépeuplé..."
Messages postés
305
Date d'inscription
lundi 7 janvier 2002
Statut
Membre
Dernière intervention
10 août 2011
5
Ben tu peux me passer un peu de ton code, il y a pas de problème.



Ceci dit, je te conseille d'utiliser les collections plutot que les
tableaux, parceque mine de pas grand chose, c'est vachement plus simple
à utiliser.



Pour t'expliquer comment manipuler les collection, j'ai besoin que tu
me dises avec quelle version du Framework tu travailles (ouais, c'est
pas tout à fait pareil entre la 1 et la 2).



Après, pour les objets recordset (je pense que c'est ce que tu utilises
en ce moment, non ?), ben c'est pas compliqué du tout. Demande moi si
tu as besoin d'explications sur ça aussi :)



Yo
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008

Alors...déjà j'suis en FrameWork 1.1...donc, rapidement, j'ai une classe qui s'occupe des connexions, et qu'a une fonction, getQueryResult retournant un Object[,] dont voici le code:



public Object[,] getQueryResult (
string query)


{



// déclaration de la requête et du DataReader puis exécution de la requête



this.oraCmd =
new OracleCommand(query,
this.oraCnx);



this.oraDtaReader =
null;



try {
this.oraDtaReader =
this.oraCmd.ExecuteReader();}



catch (Exception e) {MessageBox.Show(e.ToString());}



// déclaration du tableau de retour et initialisation des nombres de lignes et de colonnes


Object[,] ArrResult;



this.nbLignes = 0;



this.nbColonnes =
this.oraDtaReader.FieldCount;



// initialisation du tableau de retour (nombre de lignes à contenir)



while (
this.oraDtaReader.Read())


{



this.nbLignes++;


}


ArrResult =
new Object[
this.nbLignes,
this.nbColonnes];



// Remplissage du tableau de retour



try


{



this.oraDtaReader =
this.oraCmd.ExecuteReader();



int i = 0;



while (oraDtaReader.Read())


{



for (
int j = 0; j <
this.nbColonnes; j++)


{


ArrResult[i,j] = oraDtaReader.GetOracleValue(j);


}


i++;


}


}



catch (OracleException oe)


{



this.gestionErreur(oe);



return
null;


}



return ArrResult;


}



ensuite, ce que je dois faire:

¤ j'ai en base les champs que je sélectionne dans mon SELECT, à savoir MSG_ID, ENQ_TIME, FINAL_TIME, MSG_STATE, FAILURE_CODE, FAILURE_COMMENT et USER_DATA_i, avec i allant de 0 à 9 (ce qui fait 10 champs USER_DATA_)

¤ grâce à un DataSet je déclare une Table MESSAGE dans laquelle j'ajoute les champs du SELECT en colonnes et effectue le lien avec le DataSource et le DataMember de ma DataGrid...

¤ dans ma DataGrid, je dois donc afficher chaque champs à sa place (cad dans sa colonne correspondante) MAIS je ne dois afficher que les 128 premiers caractères de USER_DATA_0 (d'ou mon Result[i,6] .toString().Substring(0,128) ).

¤ quand je sélectionne la case correspondante, je dois donc afficher un TreeView contenant le découpage des champs USER_DATA_i concaténés puis traités: cette fonction est la fonction scanHL7(string str). les messages en bases sont séparés en bouts de 4ko contenus dans les USER_DATA_i. Ces messages, par norme du HL7, contiennent des segments séparés par des | et contenant eux-même des champs encore séparés par des |...la fonction scanHL7 s'occuper parfaitement bien de séparer les segments, puis les champs de chacun d'eux via une autre fonction appelée scanSegmentHL7, et d'ajouter le tout trié et traité dans le TreeView.


Enfin, voici ma fonction complète qui doit lancer la recherche (c'est une recherche par statut de message) :



private
void Bttn_LancerRech_Click(
object sender, System.EventArgs e)


{



// affichage des panels contenant le Datagrid et le TreeView


Panel_AffichMess.Visible =
true;


Panel_AffichMessTreeView.Visible =
true;


Splitter_TreeViewDataGrid.Visible =
true;



// définition de la table MESSAGE et de ses colonnes du DataGrid si ce n'est pas déjà fait



if (!dtaSet.Tables.Contains("MESSAGE"))


{


dtaSet.Tables.Add("MESSAGE");


dtaSet.Tables["MESSAGE"].Columns.Add("MSG_ID");


dtaSet.Tables["MESSAGE"].Columns.Add("ENQ_TIME");


dtaSet.Tables["MESSAGE"].Columns.Add("FINAL_TIME");


dtaSet.Tables["MESSAGE"].Columns.Add("MSG_STATE");


dtaSet.Tables["MESSAGE"].Columns.Add("FAILURE_CODE");


dtaSet.Tables["MESSAGE"].Columns.Add("FAILURE_COMMENT");


dtaSet.Tables["MESSAGE"].Columns.Add("USER_DATA_0");


DtaGrid_Result.DataSource = dtaSet;


DtaGrid_Result.DataMember = "MESSAGE";


}



else


{



// réinitialisation du dataGrid


dtaSet.Tables["MESSAGE"].Rows.Clear();


}



// on switch pour savoir quel type de recherche est demandé



switch (typeRech)


{



case ("Statut") :
// récupération du statut sous forme d'entier en accord avec ceux dans la base



string state =
null;



switch (CmboBox_Statut.SelectedIndex) {



case (0) : state = "0";
break;



case (1) : state = "2";
break;



case (2) : state = "3";
break;



case (3) : state = "4";
break;


}


Cursor.Current = Cursors.WaitCursor;


Result = connex.getQueryResult("SELECT DISTINCT DQ.MSG_ID, DQ.ENQ_TIME, DQ.FINAL_TIME, DQ.MSG_STATE, DQ.FAILURE_CODE, DQ.FAILURE_COMMENT, DQ.USER_DATA_0 " +


"FROM DXCNT_QUEUE DQ " +


"WHERE DQ.USER_DATA_0 IS NOT NULL " +


"AND DQ.MSG_STATE = " + state +


" AND DQ.QUEUE = '" + ListBox_Interfaces.SelectedItem.ToString() + "' "+


"ORDER BY MSG_ID");



if (Result.GetLength(0) > 20)


{



for (
int i=0; i<20 ; i++)


{


DataRow row = dtaSet.Tables["MESSAGE"].NewRow();


row["MSG_ID"] = Result[i,0];


row["ENQ_TIME"] = Result[i,1];


row["FINAL_TIME"] = Result[i,2];


row["MSG_STATE"] = Result[i,3];


row["FAILURE_CODE"] = Result[i,4];


row["FAILURE_COMMENT"] = Result[i,5];


row["USER_DATA_0"] = Result[i,6].ToString().Substring(0,128);



// ajout de la ligne au Datagrid et rafraîchissement de celui-ci


dtaSet.Tables["MESSAGE"].Rows.Add(row);


DtaGrid_Result.Refresh();


}


}



else


{



for (
int i=0; i < Result.GetLength(0); i++)


{


DataRow row = dtaSet.Tables["MESSAGE"].NewRow();


row["MSG_ID"] = Result[i,0];


row["ENQ_TIME"] = Result[i,1];


row["FINAL_TIME"] = Result[i,2];


row["MSG_STATE"] = Result[i,3];


row["FAILURE_CODE"] = Result[i,4];


row["FAILURE_COMMENT"] = Result[i,5];


row["USER_DATA_0"] = Result[i,6].ToString().Substring(0,128);



// ajout de la ligne au Datagrid et rafraîchissement de celui-ci


dtaSet.Tables["MESSAGE"].Rows.Add(row);


DtaGrid_Result.Refresh();


}


} // fin du case


Cursor.Current = Cursors.Default;



break;



case ("Mots Clefs") :
break;



case ("Texte Libre") :
break;


}



Voilà...si besoin est, je peux détailler davantage...merci pour ton temps et ton aide, c'est super sympa de ta part !

"Un seul Être vous manque, et tout est dépeuplé..."
Messages postés
305
Date d'inscription
lundi 7 janvier 2002
Statut
Membre
Dernière intervention
10 août 2011
5
Piouf, j'ai du mal à suivre... J'ai lu le truc, et après j'ai eu du mal à me rappeler de la question !



J'ai donc repris ton premier post.



Ton problème, si j'ai bien compris, c'est que tu ne parvenais pas à
garder le résultat de plusieurs requêtes, qui sont exécutées dans un
boucle.



Si tu fais ca :



Object[,] Result;


for (int i=0; i<10; i++)

Result = connex.getquery("SELECT... ...")



... en effet, tes résultats sont écrasés à chaque tour de boucle, et à
la sortie de ton "for", il ne te reste que le résultat de la dernière
requête.



L'idée de faire un tableau de tableaux, comme le proposaient les
autres, n'est pas mauvaise et revient à faire ce que je disait
précédemment.



Ce que je te propose donc, c'est de faire la chose suivante :



// Déclaration d'une collection (une sorte de tableaux) qui te permettra de stocker plusieurs résultats de requêtes.

Collection<Object[,]> Results = new
Collection<Object[,]>();



// Lancement de ta boucle


for (int i=0; i<10; i++){


Object[,]
Result =
connex.getquery("SELECT... ...");


Results.Add(Result);

}



A la sortie de ta boucle, tu auras alors un objet Results rempli comme il faut, avec tous les résultats de tes requêtes.



Pour traiter tes données, tu peux ensuite faire ceci :

// Pour chaque résultat...

foreach(Object[,] r in Results){

// Faire traitement sur r.

}



Au passage, n'oublie pas de faire un Result.Clear() quand tu auras fini d'utilise tes résultats.



Ensuite, j'ai détecté une petite redondance de code. Tu écris ceci :





if (Result.GetLength(0) > 20)




{




for (
int i=0; i<20 ; i++)




{




DataRow row = dtaSet.Tables["MESSAGE"].NewRow();




row["MSG_ID"] = Result[i,0];




row["ENQ_TIME"] = Result[i,1];




row["FINAL_TIME"] = Result[i,2];




row["MSG_STATE"] = Result[i,3];




row["FAILURE_CODE"] = Result[i,4];




row["FAILURE_COMMENT"] = Result[i,5];




row["USER_DATA_0"] = Result[i,6].ToString().Substring(0,128);




// ajout de la ligne au Datagrid et rafraîchissement de celui-ci




dtaSet.Tables["MESSAGE"].Rows.Add(row);




DtaGrid_Result.Refresh();




}




}




else




{




for (
int i=0; i < Result.GetLength(0); i++)




{




DataRow row = dtaSet.Tables["MESSAGE"].NewRow();




row["MSG_ID"] = Result[i,0];




row["ENQ_TIME"] = Result[i,1];




row["FINAL_TIME"] = Result[i,2];




row["MSG_STATE"] = Result[i,3];




row["FAILURE_CODE"] = Result[i,4];




row["FAILURE_COMMENT"] = Result[i,5];




row["USER_DATA_0"] = Result[i,6].ToString().Substring(0,128);




// ajout de la ligne au Datagrid et rafraîchissement de celui-ci




dtaSet.Tables["MESSAGE"].Rows.Add(row);




DtaGrid_Result.Refresh();




}



Mais tu pourrais peut être écrire celà :



for (
int i=0; i<20 && i <
Result.GetLength(0)
; i++)





{





DataRow row = dtaSet.Tables["MESSAGE"].NewRow();





row["MSG_ID"] = Result[i,0];





row["ENQ_TIME"] = Result[i,1];





row["FINAL_TIME"] = Result[i,2];





row["MSG_STATE"] = Result[i,3];





row["FAILURE_CODE"] = Result[i,4];





row["FAILURE_COMMENT"] = Result[i,5];





row["USER_DATA_0"] = Result[i,6].ToString().Substring(0,128);





// ajout de la ligne au Datagrid et rafraîchissement de celui-ci





dtaSet.Tables["MESSAGE"].Rows.Add(row);





DtaGrid_Result.Refresh();





}


De cette mannière, tu peux éviter de te retaper 2 fois le même code.



Pour ce qui est du reste, je ne suis pas vraiment certain d'avoir
compris toute la question. Si ce que je te donne ici te conviens, c'est
cool, sinon, ben on pet revoir ça ensemble.



Ha oui, dernière chose, Si tu n'arrives pas à déclarer un objet Collection (Collection<Object[,]> Results = new
Collection<Object[,]>();) Essaie de faire un using System.Collections; ou using System.Collectiong.Generic;



oualou
Messages postés
216
Date d'inscription
mardi 5 avril 2005
Statut
Membre
Dernière intervention
17 septembre 2008

Bien je vais tenter ton astuce, merci pour les détails c'est cool, j'essaie de voir ce que je peux en faire. juste une petite précision: t'es d'accord que les Result auront des choses en commun, non ...? à chaque passage dans la boucle, il va me reslectionner les autres champs que les USER_DATA_i et y'aura que ces USER_DATA_i ki changeront ? de là j'pourrais récupérer les champs qui m'intéressent, en faire une concaténation pour avoir une seule string et passer cette string à ma fameuse fonction scanHL7?

je sais pas si c'est bien clair en fait lol

"Un seul Être vous manque, et tout est dépeuplé..."
Messages postés
305
Date d'inscription
lundi 7 janvier 2002
Statut
Membre
Dernière intervention
10 août 2011
5
Bien je vais tenter ton astuce, merci pour les détails c'est cool,
j'essaie de voir ce que je peux en faire. juste une petite précision:
t'es d'accord que les Result auront des choses en commun, non ...?

--> Si tes requêtes récupèrent quelques données similaires, en effet, tu auras des choses en commun.





à
chaque passage dans la boucle, il va me reslectionner les autres champs
que les USER_DATA_i et y'aura que ces USER_DATA_i ki changeront ?

--> De ce que j'en ai compris, oui.



de là
j'pourrais récupérer les champs qui m'intéressent, en faire une
concaténation pour avoir une seule string et passer cette string à ma
fameuse fonction scanHL7?

--> Ben je crois, c'est difficile de répondre avec certitude... je ne connais pas vraiment ton application