C#-mySQL Programme trop long à s'executer.
Résolu/Ferméptisephy Messages postés 74 Date d'inscription jeudi 4 décembre 2008 Statut Membre Dernière intervention 8 novembre 2022 - 8 nov. 2022 à 11:37
- 'Mysql' n’est pas reconnu en tant que commande interne
- Cle usb non reconnu - Guide
- Invite de commande - Guide
- Pip n'est pas reconnu en tant que commande interne - Forum Python
- Npm n'est pas reconnu en tant que commande interne - Forum Javascript
- Shutdown n'est pas reconnu en tant que commande interne - Forum Windows 10
25 réponses
22 juil. 2022 à 13:44
Bonjour
tout d'abord, il y a un bug en cours sur le site avec la coloration en C#. Du coup, j'ai modifié ton message pour forcer la coloration C++ afin que cela soit plus lisible.
Pour ton problème, il y a une accumulation de "petites" choses qui misent bout à bout son consommatrices de temps et de ressources (et par effet de bord, la gestion des ressources utilisées en excès fait perdre du temps)
Tu lis plusieurs fois le fichier:
- à la ligne 14,
- à la ligne 26, alors que tu connais déjà le nombre de lignes avec la taille du tableau lines2
Donc 2 fois 500 lignes, ça ne fait que 1000 lignes, alors que 2 fois 50 000, ça en fait 100 000.
En plus ce n'est pas cohérent, puisse qu'ensuite tu inclémentes ta barre de progression à chaque fois qu'un "siren" est exporté dans excel, donc tu maximum devrais être le nombre d'items dans la List siren
Tu utilises l'api office:
c'est très très lent car l'api lance Excel et lui donne des instructions, qu'Excel exécute, l'api attend le retour d'Excel pour te donner la main etc... Il existe plein de façons de faire sans office https://lite.qwant.com/?q=C%23+write+data+xlsx+without+excel&client=opensearch
Tu peux vérifier l'influence de cette partie (sans rien changer au reste) en écrivant un fichier texte à la place d'Excel et en comparant les temps d'exécution.
A mon avis, c'est le post le plus chronophage.
Tu fais des action inutiles
- A la ligne 6, le minimum de la barre de progression ne change pas d'un fichier à l'autre, donc il faut le figer une fois pour tout dans les propriétés de la barre en mode design
- de la ligne 61 à 68, tu réinventes la roue, un objet DateTime, d'une part te donne directement ses différentes "valeurs" (aves ses propriétés Day, Month, Year, Hour, Minute, Second etc...) mais surtout sait directement exporter un texte formaté
DateTime.Now.ToString("yyyyMMdd_HHmmss")
Tu atteints peut-être un niveau critique de ressources
Tu lis les 50 000 lignes d'un coup, ça charge peut-être un peu trop ta RAM.
Plutôt que le lire entier, lis le ligne par ligne. Pour ça, il faut utiliser un streamReader.
Tu fais une boucle tant le le fichier n'est pas arrivé à la fin, dans cette boucle
- tu lignes 13 lignes, (tu peux faire une seconde boucle mais paradoxalement, ça va généralement plus vite à l'exécution de faire 13 instructions à la suite)
- tu lis la ligne que tu utilises
- Penses à incrémenter un compteur pour connaitre le maximum de ta barre de progression
27 juil. 2022 à 21:24
Dernière étape, si et seulement si les précédentes se sont bien passées : le peuplement des "Societe" par la BDD
Je ne peux pas tester, car je n'ai ni ta BDD ni les bibliothèques associées
Dans la partie Méthodes statiques, tu ajoutes
/// <summary> /// Recherche de chaque société et import des infos qui la concerne /// </summary> public static void PeuplerListeSocieteParBDD(List<Societe> Societes) { MonLog("========================"); MonLog($"Début peuplement BDD à {DateTime.Now:HH-mm-ss.fff}"); MySqlConnection conn; MySqlDataReader monreader = null; string server = "server"; string database = "mabse"; string user = "monuser"; string password = "monpass"; string port = "2222"; string connString = $"Server={server}; Port={port};Database={database};Uid={user};Pwd={password};SSL Mode=None;default command timeout=0"; string marequete = ""; conn = new MySqlConnection(connString); try { conn.Open(); foreach(Societe s in Societes) { MonLog($"Siren à chercher {s.Siren}"); marequete = " select t0.tesccpcod, " + "t0.numero, " + "t0.identifiant, " + "t0.xxxxx, " + "t0.xxxxx, " + "t0.xxxxx, " + "t1.xxxxx," + "t2.xxxxx," + "t2.xxxxxx," + "t2.xxxxxx," + "t1.xxxxxx," + "t1.xxxxxx," + "t1.xxxxxx " + "from tes000pf t0 " + "left join tes001pf t1 on t1.ccccc = t0.ccccc " + "left join tes002pf t2 on t2.ccccc = t0.ccccc " + "left join tes003pf t3 on t3.ccccc = t0.ccccc " + "left join tes004pf t4 on t4.ccccc = t0.ccccc " + "where t0.numero ='" + s.Siren + "'"; MonLog("Ma requete utilisé:" + marequete); MonLog("sirens :" + s.Siren); MySqlCommand cmd = new MySqlCommand(marequete, conn); monreader = cmd.ExecuteReader(); if (monreader.Read()) //while { //recuperation des données s.Numcode = monreader.GetString(0); s.Matadh = monreader.GetString(1); s.Solmon = monreader.GetString(2); s.Soldat = monreader.GetString(3); s.Adhfer = monreader.GetString(4); s.Raison = monreader.GetString(5); s.Milib = monreader.GetString(6); s.Emibas = monreader.GetString(7); s.Emicoe = monreader.GetString(8); s.Debdat = monreader.GetString(9); s.Findat = monreader.GetString(10); s.Datrec = monreader.GetString(11); monreader.Close(); } }//fin du for MonLog("********* FIn de la boucle - sauvegarde du fichier excel ********** "); } catch (MySqlException erreur) { MonLog("******** ERREUR DANS LE TRAITEMENT :" + erreur.ToString()); conn.Close(); } catch (Exception e) { MonLog("=========Erreur==============="); MonLog(e.StackTrace); MonLog("=========Fin Erreur==============="); } MonLog($"Fin peuplement BDD à {DateTime.Now:HH-mm-ss.fff}"); MonLog("========================"); }
Et dans le formulaire
List<Societe> societes = Societe.InitFromFichierSiren("FICHIER-anonyme.txt"); Societe.PeuplerListeSocieteParBDD(societes); Societe.ExportListeSocieteToExcel(societes, "FICHIER-anonyme.xlsx");
25 juil. 2022 à 14:41
Bonjour,
merci pour tes conseils, j'ai commencé à optimiser un peu tout ça mais j'ai du mal à trouver autre chose, pour générer mon fichier excel, je vais essayer de creuser la chose.
Je tente de le faire avec Oledb mais j'ai du mal à saisir le concept.
25 juil. 2022 à 15:28
Oledb c'est un "vieux" moteur de base de données.
Mais Excel est compatible.
Sinon, si tu as l'habitude de Linq, le NuGet Linq to xls est pas mal.
26 juil. 2022 à 14:50
Bonjour,
pour répondre à ta question, je ne connais pas trop linq, ni le nuget, cela fait longtemps que je n'est plus fait de c#. Je fais des programmes pour dépanner, mais à l'orgine quand j'ai bossé, j'ai juste repris quelques programme que j'ai améliorer, mais j'ai pas fais de gros développement ...:(
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionModifié le 26 juil. 2022 à 16:12
Bonjour,
j'ai modifié mon code, en esperant que ça puisse changer quelque chose, avec ce que j'ai appris recemment.
J'ai créé des liststring et j'ai enregistré les valeurs que j'ai récupéré dans chacune des variables, voici comment j'ai procédé :
namespace Suivi_tese { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private FolderBrowserDialog folderBrowserDialog2; private bool selfichier; private bool selrepertoire; private static string repexc = ""; private static MySqlConnection conn; private static MySqlDataReader monreader = null; protected Range Cellules; protected Range UneCellule; List<string> numcode = new List<string>(); List<string> matadh = new List<string>(); List<string> solmon = new List<string>(); List<string> soldat = new List<string>(); List<string> adhfer = new List<string>(); List<string> raison = new List<string>(); List<string> milib = new List<string>(); List<string> emibas = new List<string>(); List<string> emicoe = new List<string>(); List<string> debdat = new List<string>(); List<string> findat = new List<string>(); List<string> datrec = new List<string>(); public string ReturnReaderValue(MySqlDataReader reader, int indexe) { if (!reader.IsDBNull(indexe)) { return reader.GetString(indexe); } else { return ""; } } private void btn_start_ficExcel_Click_1(object sender, EventArgs e) { BasicConfigurator.Configure(); string path = @"C:\Users\.........\test\log.txt"; log.Info("--------------------"); log.Info("Debut de traitement"); log.Info("--------------------"); log.Info("Chemin du fichier pour le log " + path); if (selrepertoire == true & selfichier == true) { log.Info("Selection OK"); int compteur = 0; // LBLRES.Text = compteur.ToString(); // Set Minimum to 1 represente la 1ere ligne mabarre.Visible = true; string FileToRead = txtbox_entree.Text; log.Info("Fichier dub choisi" + txtbox_entree.Text); /* RECUPERATION DES SIRENS */ #region Recuperation_sirens int moncompteur = 0; String[] lines2 = File.ReadAllLines(FileToRead); List<String> sirens = new List<String>(); for (Int32 index = 2; index < lines2.Count(); index += 14) { if (lines2[index].Substring(0, 5) == "Info1") { sirens.Add(lines2[index].Substring(6, 14)); moncompteur++; } } log.Info("Mon compteur :" + moncompteur); // Set Maximum - correspond au nombre de ligne du fichier mabarre.Maximum = sirens.Count; // Set the initial value of the ProgressBar. mabarre.Value = 1; #endregion /* Connexion à la base mysql */ string server = "server"; string database = "mabse"; string user = "monuser"; string password = "monpass"; string port = "2222"; string connString = "Server=" + server + "; Port=" + port + ";Database=" + database + ";Uid=" + user + ";Pwd=" + password + ";SSL Mode=None;default command timeout=0"; string marequete = ""; conn = new MySqlConnection(connString); try { conn.Open(); /* CREATION ET OUVERTURE DU FICHIER EXCEL */ repexc = folderBrowserDialog2.SelectedPath + "\\dossier" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".xlsx"; Microsoft.Office.Interop.Excel.Application xla = new Microsoft.Office.Interop.Excel.Application(); xla.Visible = false; Workbook wb = xla.Workbooks.Add(XlSheetType.xlWorksheet); //WorksheetCollection worksheets = xla.Worksheets; Worksheet ws = (Worksheet)xla.ActiveSheet; ws.Cells[1, 1] = "colonne 1"; ws.Cells[1, 2] = " colonne 2"; ws.Cells[1, 3] = " colonne 3"; ws.Cells[1, 4] = " colonne 4"; ws.Cells[1, 5] = "colonne 5"; ws.Cells[1, 6] = "colonne 6"; ws.Cells[1, 7] = "colonne 7"; ws.Cells[1, 8] = "colonne 8"; ws.Cells[1, 9] = "colonne 9"; ws.Cells[1, 10] = "colonne 10"; ws.Cells[1, 11] = "colonne 11"; ws.Cells[1, 12] = "colonne 12"; ws.Cells[1, 13] = "colonne 13"; UneCellule = ws.get_Range("A1", "M1"); ws.Columns.Font.Name = "MS Sans Serif"; ws.Columns.Font.Size = 12; int cptCol = 2; /* Parcours de la base de données et récupération du résultat */ int compteurAnnexe = 0; for (int a = 0; a < sirens.Count; a++) { marequete = " select t0.tesccpcod, " + "t0.numero, " + "t0.identifiant, " + "t0.xxxxx, " + "t0.xxxxx, " + "t0.xxxxx, " + "t1.xxxxx," + "t2.xxxxx," + "t2.xxxxxx," + "t2.xxxxxx," + "t1.xxxxxx," + "t1.xxxxxx," + "t1.xxxxxx " + "from tes000pf t0 " + "left join tes001pf t1 on t1.ccccc = t0.ccccc " + "left join tes002pf t2 on t2.ccccc = t0.ccccc " + "left join tes003pf t3 on t3.ccccc = t0.ccccc " + "left join tes004pf t4 on t4.ccccc = t0.ccccc " + "where t0.numero ='" + sirens[a] + "'"; log.Info("Ma requete utilisé:" + marequete); log.Info("sirens :" + sirens[a]); MySqlCommand cmd = new MySqlCommand(marequete, conn); monreader = cmd.ExecuteReader(); if (monreader.Read()) //while { //recuperation des données numcode.Add(ReturnReaderValue(monreader, 0)); //code matadh.Add(ReturnReaderValue(monreader, 1)); //siret solmon.Add(ReturnReaderValue(monreader, 2)); // matadh soldat.Add(ReturnReaderValue(monreader, 3)); adhfer.Add(ReturnReaderValue(monreader, 4)); raison.Add(ReturnReaderValue(monreader, 5)); milib.Add(ReturnReaderValue(monreader, 6)); emibas.Add(ReturnReaderValue(monreader, 7)); emicoe.Add(ReturnReaderValue(monreader, 8)); debdat.Add(ReturnReaderValue(monreader, 9)); findat.Add(ReturnReaderValue(monreader, 10)); datrec.Add(ReturnReaderValue(monreader, 11)); //enregistrement dans mon fichier excel ws.Cells[cptCol, 1] = numcode[compteurAnnexe]; ws.Cells[cptCol, 2] = matadh[compteurAnnexe]; ws.Cells[cptCol, 3] = solmon[compteurAnnexe]; ws.Cells[cptCol, 4] = soldat[compteurAnnexe]; ws.Cells[cptCol, 5] = adhfer[compteurAnnexe]; ws.Cells[cptCol, 6] = raison[compteurAnnexe]; ws.Cells[cptCol, 7] = milib[compteurAnnexe]; ws.Cells[cptCol, 8] = emibas[compteurAnnexe]; ws.Cells[cptCol, 9] = emicoe[compteurAnnexe]; ws.Cells[cptCol, 10] = debdat[compteurAnnexe]; ws.Cells[cptCol, 11] = findat[compteurAnnexe]; ws.Cells[cptCol, 12] = datrec[compteurAnnexe]; compteurAnnexe++; cptCol++; mabarre.PerformStep(); } else { ws.Cells[cptCol, 2] = sirens[a]; cptCol++; } mabarre.PerformStep(); monreader.Close(); compteur++; LBLRES.Text = compteur.ToString(); }//fin du for log.Info("********* FIn de la boucle - sauvegarde du fichier excel ********** " ); ws.SaveAs(repexc, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); xla.Quit(); MessageBox.Show("Fin du traitement", "Message d'information", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch (MySqlException erreur) { log.Info("******** ERREUR DANS LE TRAITEMENT :" + erreur.ToString()); MessageBox.Show(erreur.ToString()); conn.Close(); } log.Info("----------- FIN DE TRAITEMENT -----------"); } else { log.Info("Fin du traitement du traitement - KO "); log.Error("AUcun Fichier ou dossier selectoinné"); MessageBox.Show("Merci de choisir un fichier et un répretoire de sortie", "Message d'information", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } // monstream.Close(); } }//fin méthode public parital class }//fin du namespace
mais quand j'ai des petits fichiers, ça marche, mais quand il est plus lours ( environ 50k de ligne) le fichier en entrée, le programme bug, d'après mon log, il s'arrete puis il ne fait plus rien, c'est agaçant.
J'avais un programme que j'ai récupéré pour y faire deux trois modification, même lui fonctionné, on devait attendre un moment puis il reparté mais là il ne me fait rien, comment ça se fait?
Pourtant j'ai 16go de ram et presque 1to dans mon disque dur,.
merci
Modifié le 26 juil. 2022 à 16:13
Je pensais à une chose, avec le code suivant :
/* RECUPERATION DES SIRENS */ #region Recuperation_sirens int moncompteur = 0; String[] lines2 = File.ReadAllLines(FileToRead); List<String> sirens = new List<String>(); for (Int32 index = 2; index < lines2.Count(); index += 14) { if (lines2[index].Substring(0, 5) == "Info1") { sirens.Add(lines2[index].Substring(6, 14)); moncompteur++; } }
meme si mon fichier en entrée est volumineux, ce code récupère chaque siren dans un tableau, donc par exemple, pour un fichier avec 1000 lignes, je peux n'avoir que 50 ou 100 sirens, ce qui est negligeable, mais là mon programme tourne puis il s'arrete sans raison et je n'ai pas d'indication dans mes logs.
Merci
26 juil. 2022 à 18:17
Tout d'abord, il ne faut pas utiliser 12 listes de string, mais une seule liste d'une classe que tu auras écrites dont les propriétés sont au moins les 12 paramètres dont tu as besoin.
Mais ça c'est si et seulement si tu as besoin des ces données ailleurs dans le programme.
Dans ce que tu montres, les listes ne servent à rien à part charger encore plus la RAM inutilement.
Dans ton précédent code, tu avais ça
nomcol1 = monreader.GetString(0); nomcol2 = monreader.GetInt64(1).ToString(); nomcol3 = monreader.GetString(2); ........ //jusque là pas de soucis je recupère mon résultat //je rempli mon tableau pour rempli le fichier excel ws.Cells[a, 1] = nomcol1; ws.Cells[a, 2] = nomcol2; ...............
Donc 12 strings qui été réutilisées à chaque boucle, ce qui est une utilisation faible de la RAM.
Pour utiliser encore un peu moins de RAM tu aurais pu faire ça
//je rempli mon tableau pour rempli le fichier excel ws.Cells[a, 1] = monreader.GetString(0); ws.Cells[a, 2] = monreader.GetInt64(1).ToString(); ...............
Et donc coup, cela tend à faire penser que tu n'as pas besoin de ces données plus loin dans ton programmes.
Et maintenant, non seulement tu stockes toutes tes valeurs dans des listes (ce qui à chaque nouvelle valeur consomme de plus en plus de RAM), mais au lieu de lire dans le reader tu fais appel à une méthode, donc des appels supplémentaires ce qui est consommateur de temps et d'un peu de mémoire.
Quand on cherche à en gagner, on n'en rajoute pas inutilement.
Concernant
mais là mon programme tourne puis il s'arrete sans raison et je n'ai pas d'indication dans mes logs.
s'il n'y a rien dans les logs concernant la progression de l'import (puis que le code correspondant à ce texte est celui de l'import) c'est d'abord parce que tu n'y loggues rien.
Tu peux essayer ça
if (lines2[index].Substring(0, 5) == "Info1") { sirens.Add(lines2[index].Substring(6, 14)); moncompteur++; log.Info(string.Format("Ligne n°{0} importée, son contenu est '{1}'", index, lines2[index]); }
Note l'utilisation de string.Format qui est beaucoup plus pratique pour construire des string que la concaténation (si tu codes avec VS 2019 ou 2022, il y a une version encore plus simple)
En plus, il n'y a qu'un seul try catch, plus tard et ce try catch ne gère qu'un seul type d'erreurs, il suffit de n'importe quelle autre pour que ça plante sans log et potentiellement sans message d'erreur.
D'ailleurs, les logs normalement ça sert en production pas pendant le développement, sauf sur du temps réel mais là ce n'est pas le cas.
Laisse le programme en débug planter pour pouvoir débogger.
Enfin
Pourtant j'ai 16go de ram et presque 1to dans mon disque dur,.
Oui mais c'est windows qui choisit combien de RAM et de Swap seront disponibles pour ton programme et ça ne sera qu'une infime partie de tout ça.
PS 1, la coloration en C# ne fonctionne plus, merci de sélectionner C++, c'est compatible à 95% au moins, ce sera plus simple à lire.
PS 2, peux tu constituer un fichier exemple d'une 50 lignes anonymisées mais vraiment représentatives (si une données fait 6 chiffres, il faut qu'il y en ait 6 etc...) et le mettre en ligne sur cjoint ou équivalent et poster le lien ici?
27 juil. 2022 à 09:02
BOnjour,
j'ai fais une copie d'écran du processus, quand j'execute le programme, au début il tourne normalement, mais après plus rien :
27 juil. 2022 à 09:09
J'ai mis en pièce jointe via ce lien, c'est un fichier au format txt :
https://www.cjoint.com/c/LGBheirWdWI
C'est bien vu au niveau des try, je vais tenter d'en mettre pour ovir ce qu'il se passe également.
Pour ce qui est des logs, je m'en sert pour avoir une trace du traitement, comme ça une fois le programme en production, je vais juste modifier le chemin du dossier et on aura toujours une trace.
Pour exemple, le fichire ci joint possede 126 lignes, dans ce fichire je récupère que 9 sirens. J'ai tenté avec un fichier de production, qui fait environ 5824 lignes, il y a 32 sirens ( de mémoire) dont normalement ce n'est pas grand chose.
J'ai connu des programmes qui faisait plus d'opération mais qui s'executé jusqu'au bout, mais lui.... c'est un mystère, pour l'instant.
Au fait, j'ai un peu surestimé le nombre de ligne des fichires, ce ne sont pas des fichires avec 50k de lignes mais plutot entre 5000 et 6000 lignes, dont ça devrait normalement pouvoir le faire.
Merci
27 juil. 2022 à 11:09
J'ai ce genre de message qui revient continuellement, quand j'utilise un fichier de 5000 lignes. Il dit que le thread s'est arreté, j'ai l'impression qu'il a stoppé le traitement en plein milieu, je ne sais pas pourquoi.
27 juil. 2022 à 11:43
J'ai debogué pas a pas et j'ai remarqué une chose , est ce que je m'y prend bien ?
Car dans ma boucle for, j'ai ceci à la fin :
monreader.close()
monreader.dispose();
et c'est à partir de là que le programme cesse de tourner , quand mon compteut a=4, c'est etrange.
27 juil. 2022 à 16:26
En commençant par la fin, la ligne où tu fermes le reader, ne me parait pas problématique puisque tu le réalimentes à chaque itération. Mais je n'en suis pas certain je n'utilise que très rarement des bases de données et mon dernier projet avec un reader a plus de 15 ans...
Le thread qui s'arrête régulièrement n'est pas le tien, ça peut par exemple être les appels à la base de données que le reader exécute.
Pour le reste, je tacherais de trouver un moment dans la soirée pour faire un test.
Là je suis dans les transports en commun, je vais tacher de jeter un œil au fichier
27 juil. 2022 à 18:23
Le fichier que tu as fourni n'est pas lu pas ton code.
Il y a ça
if (lines2[index].Substring(0, 5) == "Info1") { sirens.Add(lines2[index].Substring(6, 14));
Si je regarde la 3eme ligne du fichier, elle ne commence pas par Info1, par contre, il y a un nombre de 14 chiffres à l'index 6.
A l'inverse la première ligne, commence par Informations1, mais les 14 caractères à partir de l'index 6 sont
"ation1 "
Pour la suite de mon test, je vais partir du principe, que la ligne ne commence pas par "Info1".
27 juil. 2022 à 19:10
Procédons par étapes.
D'abord, je n'ai pas ta base de données, donc c'est une partie que je ne peux pas tester.
Du coup, je vais remplir les "Sociétés" par des suites de 10 caractères. Chaque suite sera unique pour une "cellule" du fichier de sortie.
Dans un premier temps, on va exporter un csv.
Dans ton projet, tu vas ajouter une classe nommée Societe.
Dans le fichier Societe.cs tu vas mettre ce code
class Societe { //Chaque propriété est une information utile ultérieurement public string Siren { get; set; } public string Numcode { get; set; } public string Matadh { get; set; } public string Solmon { get; set; } public string Soldat { get; set; } public string Adhfer { get; set; } public string Raison { get; set; } public string Milib { get; set; } public string Emibas { get; set; } public string Emicoe { get; set; } public string Debdat { get; set; } public string Findat { get; set; } public string Datrec { get; set; } #region Méhodes de classe /// <summary> /// Retourne cette instance sous la forme d'une string compilée en ligne de csv /// </summary> /// <returns></returns> public string ToCsv() { return $"{Numcode};{Matadh};{Solmon};{Soldat};{Adhfer};{Raison};{Milib};{Emibas};{Emicoe};{Debdat};{Findat};{Datrec}"; } #endregion #region Méthodes statiques /// <summary> /// Importe le fichier Siren et initie la liste de societés /// </summary> /// <param name="Filename"></param> /// <returns></returns> public static List<Societe> InitFromFichierSiren(string Filename) { MonLog("========================"); MonLog($"Début import Sirens à {DateTime.Now:HH-mm-ss.fff}"); List<Societe> res = new List<Societe>(); try { string[] lignes = File.ReadAllLines(Filename); for (int i = 2; i < lignes.Count(); i += 14) { string siren = lignes[i].Substring(6, 14); res.Add(new Societe { Siren = siren }); MonLog($"Ligne n°{i} inmportée, siren : {siren}"); } } catch (Exception e) { MonLog("=========Erreur==============="); MonLog(e.StackTrace); MonLog("=========Fin Erreur==============="); } MonLog($"Fin import Sirens à {DateTime.Now:HH-mm-ss.fff}"); MonLog("========================"); return res; } /// <summary> /// Permet de logguer dans le fichier en mode Realease et dans la console en mode Debug /// </summary> /// <param name="Texte"></param> private static void MonLog(string Texte) { #if DEBUG Console.WriteLine(Texte); #else log.Info(Texte); #endif } #if DEBUG /// <summary> /// Comme je n'ai pas ta base de données me permet de mettre des datas dans la liste de societé /// De ton coté, ça permettra un premier test d'export Excel sans accès à la bdd /// </summary> /// <param name="Societes"></param> public static void DebugPeuplerListeSocietesSansBdd(List<Societe> Societes) { MonLog("========================"); MonLog("Début peuplement débug"); int i = 64; foreach (Societe s in Societes) { s.Adhfer = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Datrec = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Debdat = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Emibas = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Emicoe = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Findat = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Matadh = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Milib = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Numcode = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Raison = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Soldat = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; s.Solmon = new string(Convert.ToChar(i++), 10); //10 fois le caractère i; MonLog($"Peuplement {s.ToCsv()}"); i++; if (i == 127) i = 64; } MonLog("Fin peuplement débug"); MonLog("========================"); } #endif /// <summary> /// Exporte les datas dans un fichiers csv /// </summary> /// <param name="Societes"></param> /// <param name="FileName"></param> public static void ExportListeSocieteToCsv(List<Societe> Societes, string FileName) { MonLog("========================"); MonLog($"Début export CSV à {DateTime.Now:HH-mm-ss.fff}"); List<string> res = new List<string> { "colonne 1;colonne 2;colonne 3;colonne 4;colonne 5;colonne 6;colonne 7;colonne 8;colonne 9;colonne 10;colonne 11;colonne 12;colonne 13" }; res.AddRange(Societes.Select(s => s.ToCsv())); File.WriteAllLines(FileName, res); MonLog($"Fin export CSV à {DateTime.Now:HH-mm-ss.fff}"); MonLog("========================"); } #endregion }
Dans ton formulaire, tu pourras tester ce code de cette façon
List<Societe> societes = Societe.InitFromFichierSiren("FICHIER-anonyme.txt"); Societe.DebugPeuplerListeSocietesSansBdd(societes); Societe.ExportListeSocieteToCsv(societes, "FICHIER-anonyme.csv");
Note, j'ai écrit une méthode qui "choisit" de logguer dans le fichier ou la console selon que tu sois en mode Realease ou Debug, l'avantage de la console c'est qu'on voit en live ce qui se passe.
Pour mon test ça donne
======================== Début import Sirens à 19-08-05.306 Ligne n°2 inmportée, siren : 08755006600029 Ligne n°16 inmportée, siren : 30168546980011 Ligne n°30 inmportée, siren : 30653515478983 Ligne n°44 inmportée, siren : 31189866415003 Ligne n°58 inmportée, siren : 31145294300014 Ligne n°72 inmportée, siren : 31441251105477 Ligne n°86 inmportée, siren : 31490147500002 Ligne n°100 inmportée, siren : 47584529000013 Ligne n°114 inmportée, siren : 31825157578539 Fin import Sirens à 19-08-05.354 ======================== ======================== Début peuplement débug Peuplement HHHHHHHHHH;FFFFFFFFFF;KKKKKKKKKK;JJJJJJJJJJ;@@@@@@@@@@;IIIIIIIIII;GGGGGGGGGG;CCCCCCCCCC;DDDDDDDDDD;BBBBBBBBBB;EEEEEEEEEE;AAAAAAAAAA Peuplement UUUUUUUUUU;SSSSSSSSSS;XXXXXXXXXX;WWWWWWWWWW;MMMMMMMMMM;VVVVVVVVVV;TTTTTTTTTT;PPPPPPPPPP;QQQQQQQQQQ;OOOOOOOOOO;RRRRRRRRRR;NNNNNNNNNN Peuplement bbbbbbbbbb;``````````;eeeeeeeeee;dddddddddd;ZZZZZZZZZZ;cccccccccc;aaaaaaaaaa;]]]]]]]]]];^^^^^^^^^^;\\\\\\\\\\;__________;[[[[[[[[[[ Peuplement oooooooooo;mmmmmmmmmm;rrrrrrrrrr;qqqqqqqqqq;gggggggggg;pppppppppp;nnnnnnnnnn;jjjjjjjjjj;kkkkkkkkkk;iiiiiiiiii;llllllllll;hhhhhhhhhh Peuplement ||||||||||;zzzzzzzzzz;;~~~~~~~~~~;tttttttttt;}}}}}}}}}};{{{{{{{{{{;wwwwwwwwww;xxxxxxxxxx;vvvvvvvvvv;yyyyyyyyyy;uuuuuuuuuu Peuplement ??????????;??????????;??????????;??????????;;??????????;??????????;??????????;??????????;??????????;??????????;?????????? Peuplement ??????????;??????????;??????????;??????????;??????????;??????????;??????????;??????????;??????????;;??????????; Peuplement ££££££££££;¡¡¡¡¡¡¡¡¡¡;¦¦¦¦¦¦¦¦¦¦;¥¥¥¥¥¥¥¥¥¥;??????????;¤¤¤¤¤¤¤¤¤¤;¢¢¢¢¢¢¢¢¢¢;??????????;??????????;; ;?????????? Peuplement °°°°°°°°°°;®®®®®®®®®®;³³³³³³³³³³;²²²²²²²²²²;¨¨¨¨¨¨¨¨¨¨;±±±±±±±±±±;¯¯¯¯¯¯¯¯¯¯;««««««««««;¬¬¬¬¬¬¬¬¬¬;ªªªªªªªªªª;;©©©©©©©©©© Fin peuplement débug ======================== ======================== Début export CSV à 19-08-05.354 Fin export CSV à 19-08-05.371 ========================
Et un fichier CSV parfaitement exploitable sous Excel
27 juil. 2022 à 19:56
2eme étape, seulement si la précédente s'est bien passée.
Tu vas aller dans la gestion des packages NuGet
Tu recherches MiniExcel et tu l'installe (je m'étais trompé Lind To Excel, c'est pour lire les fichiers xlsx)
27 juil. 2022 à 19:59
Ensuite dans la classe, à la région Méthodes de classe tu ajoutes
/// <summary> /// Retourne un dictionnaire compatible de MiniExcel /// </summary> /// <returns></returns> public Dictionary<string, object> ToMiniExcel() { Dictionary<string, object> res = new Dictionary<string, object>(); res.Add("Colonne 1", Numcode); res.Add("Colonne 2", Matadh); res.Add("Colonne 3", Solmon); res.Add("Colonne 4", Soldat); res.Add("Colonne 5", Adhfer); res.Add("Colonne 6", Raison); res.Add("Colonne 7", Milib); res.Add("Colonne 8", Emibas); res.Add("Colonne 9", Emicoe); res.Add("Colonne 10", Debdat); res.Add("Colonne 11", Findat); res.Add("Colonne 12", Datrec); return res; }
Et à la région Méthodes statiques tu ajoutes
/// <summary> /// Exporte les datas dans un fichier xlsx /// </summary> /// <param name="Societes"></param> /// <param name="FileName"></param> public static void ExportListeSocieteToExcel(List<Societe> Societes, string FileName) { MonLog("========================"); MonLog($"Début export Excel à {DateTime.Now:HH-mm-ss.fff}"); List<Dictionary<string, object>> res = new List<Dictionary<string, object>>(); res.AddRange(Societes.Select(s => s.ToMiniExcel())); if (File.Exists(FileName)) File.Delete(FileName); MiniExcel.SaveAs(FileName, res); MonLog($"Fin export Excel à {DateTime.Now:HH-mm-ss.fff}"); MonLog("========================"); }
29 juil. 2022 à 07:43
Bonjour,
merci pour ton retour.
Je vais regarder tout ça à tete reposer et teser cela :)
en parallèle, j'avais trouvé la raison pourquoi le programme ne tournait pas..... dans ma base phpmyadmin il n'y avait pas de clé primaire.
Lorsque m'on collegue à fait l'export de la base ( de l'as400 vers mysql) il n'a pris que les données brut, quand j'ai découvert cela, j'ai créé les clefs primaires et je suis en train de tester les jointures, mais comme je reprend des données de plusieurs tables, plus je met de jointure, plus mon programme est lent.
Je vais tester cela et je reviens vers toi, merci beaucoup :)
30 juil. 2022 à 09:36
Je pense que les données brut exportées de la base ( de l'as400 vers mysql) ne permettent pas d'exploiter les données. Je crains qu'il manque les liens entre les tables. A moins qu'il n'y ait dans les données brutes des champs que tu n'as pas remarqué et qui pourraient être utilisés comme lien.
Tu ne donnes pas assez d'information pour que je puisse être plus précis ou donner un exemple de ce qui manque.
Quel logiciel de bases de données était utilisé dans l'AS400?
29 juil. 2022 à 07:55
De rien.
Je suis en congés quelques temps, et je n'aurais pas accès à un IDE.
Je pourrais répondre à des questions simples mais pas plus.
29 juil. 2022 à 10:30
merci c'est super gentil :)
29 juil. 2022 à 16:09
Pour faire suite à mon poste, voila ma problèmatique.
J'ai découvert qu'en fait c'était un problème de requête, car lors de l'export de la base mysql, il n'y avait que les données brut, pas de clé primaire.
J'ai donc pour chacune des tables rajouté une colonne que je nommerais "identifiant" en auto-increment, donc j'ai fait cela sous phpmyadmin et il m'a créé les colonnes sans problemes, voici un peu la structure des mes tables :
Lorsque j'ai créé pour chaque tables ( sous mysql phpmyadmin) la colonne id, en début de table, ça marché et il était en auto increment, du coup les colonnes id se sont rempli.
Pour chacune des tables, voici leur nombre de ligne :
table0: 1390 lignes
table1: 62 347
table2 : 126164
table3 : 15 589
table 4: 16 000.
moi je ne vais faire que de la consultation, pas d'insertion.
Voici la requete que j'utilise :
marequete = " select t0.code , t0.siret, t0.numentreprise, t0.solde, t0.datesolde, t0.champs, t1.nomentreprise, t2.libelle, t2.base t2.emission, t1.debit, t1.datefin, t1.daterec, t2.colonnex, t1.colonnex, t3.colonnez, t3.colonnez, t3.TESENCFIN, " + t1.colonnetotale " + from table0 t0 " + left join table1 t1 on t0.numsiret = t1.numsiret " + left join table2 t0 on t0.numsiret = t2.numsiret " + left join table3 t3 on t3.numsiret = t1.numsiret " + where t0.siret = " + monsiren[a] + "";
mais j'ai l'impression que plus ma requete est longue, plus le programme est long ( j'ai fais le test ) et je n'arrive pas à l'optimiser. J'ai fais ma jointure sur le numero de siret et j'ai utilisé left join, car d'une table à l'autre, un siret peut ne pas être là.
Par contre si je fais ma jointure sur l'id ça ne marche pas , car ce sont des donnée autoincrement, que j'ai créé dans l'export des tables brut qui a été réalisé, vous voyez un peu la complexité de la chose, d'où la jointure sur le numero de siret.
Y a t-il un moyen de l'optimiser pour rendre le programme viable?
sinon pour ma part je suis en congés fin du mois d'aout) ça va faire du bien^
Un grand merci ^
30 juil. 2022 à 09:24
Il est peut-être préférable de commencer une nouvelle discussion, ce serait plus clair.
Je pense que tes tables sont mal structurées, et que ton problème principal, ce n'est pas un problème de performance, mais le fait que les données que tu vas récupérer de ta requête ne sont pas correctes. Pour structurer correctement ces tables, il faut tenir compte de à quoi elles servent, et tu ne nous donnes aucune information à ce sujet.
Je pense qu'il faut adapter ainsi:
- le champ numsiret devrait probablement être présent dans une seule table, et ne pas être utilisé pour les jointures
- pour lier deux tables, tu dois utiliser les id. Par exemple, si tu as une table facture et une table entreprise, tu auras dans la table facture un champ avec id_entreprise.
- les jointures se font avec les id
Il est possible que le problème vienne de l'exportation, qui aurait laissé tombé les liens entre le tables.