C#-mySQL Programme trop long à s'executer.

Résolu

Bonjour,

j'ai un soucis, avec mon programme. J'ai une application windowsform, toute simple, avec un bouton pour aller chercher un fichier , un bouton parcourir pour choisir un dossier de destination, pour créer un fichier excel en sortie et un bouton pour "lancer le traitement".
 

j'ai également mis une progressbar afin de voir le résultat., voici le principe de fonctionnement :

une fois mon fichier choisi, mon programme va parcourir chaque ligne du fichieret je souhaite recupérer le siren toutes les 14 lignes ( voir partie dans le code recupération des sirens).

Ceci fait, sur un fichier échantillon, j'ai bien tous les siren dans mon tableau.

Ensuite je vais parcourir mon tableau faire une requete qui va prendre pour condition sirens[a] et après je vais récupérer le résultats de la requete dans des variables, puis je constitut mon fichier excel.

Le problème : quand je choisi un fichire petit, avec moins de  500 lignes, ça marche, mais si j'en choisi un plus volumineux, mon programme tourne puis s'arrete et plus rien ne marche. Le soucis c'est qu'en production je vais avoir des fichires de 50 000 lignes.

J'ai fais la monté de version de visual studio 2022 mais ça n'a rien changé et j'utilise le framework .net 4.7.2.

 
    private void btn_start_ficExcel_Click(object sender, EventArgs e)
        {
            // Set Minimum to 1 represente la 1ere ligne
            mabarre.Visible = true;
            mabarre.Minimum = 1;
 
            string FileToRead = txtbox_entree.Text;
 
            /*
                RECUPERATION DES SIRENS
             */
 
            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) == "DT1DT")
                {
                    sirens.Add(lines2[index].Substring(6, 14));
 
                }
 
            }
            // Set Maximum  - correspond au nombre de ligne du fichier
            mabarre.Maximum = File.ReadAllLines(FileToRead).Length;
            // Set the initial value of the ProgressBar.
            mabarre.Value = 1;
            // Set the Step property - 1 chaque ligne lu
            //mabarre.Step = 1;
            /*
               Connexion à la base mysql
            */
            string server = "xxxxxxxxx";
            string database = "xxxxxx";
            string user = "xxxxxxx";
            string password = "xxxxxxxx";
            string port = "xxxxxxx";
 
            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();
            }
            catch (MySqlException erreur)
            {
                MessageBox.Show(erreur.ToString());
                conn.Close();
            }
 
 
            /*
           CREATION ET OUVERTURE DU FICHIER EXCEL
        */
            DateTime today = (DateTime.Now).AddMonths(-1);
            string d = Convert.ToString(today);
            string yyyy = d.Substring(6, 4);
            string mm = d.Substring(3, 2);
            string jour = d.Substring(0, 2);
            string heure = d.Substring(11, 2);
            string minute = d.Substring(14, 2);
            string seconde = d.Substring(17, 2);
 
            repexc = folderBrowserDialog2.SelectedPath + "\\mondossier" + yyyy + mm + jour + "_" + heure + minute + seconde + ".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";
			...............
			...............
			//je créé les différents entete
 
            UneCellule = ws.get_Range("A1", "M1");
            ws.Columns.Font.Name = "MS Sans Serif";
            ws.Columns.Font.Size = 12;
 
 
            string nomcol1 = "";
            string nomcol2 = "";
            string nomcol3 = "";
			........
			....... //je créé les différentes variables
 
 
            /*
                Parcours de la base de données et récupération du résultat
            */
 
			
            for (int a = 2; a < sirens.Count; a++) //
            {
 
                marequete=" select t0.tesccpcod, "+
               "t0.col1, "+
               "t0.col2, " +
               "t0.col3, " +
               "t0.xxxx, " +
               "t0.xxxx, " +
               "t1.xxxx," +
               "t2.xxxx," +
               "t2.xxxx," +
               "t2.xxxx," +
                "t1.xxxx," +
                "t1.xxxxx," +
                "t1.xxxx " +
                "from matable0 t0 " +
                 "INNER join matable1 t1 on t1.xxxx = t0.xxx " +
                 "inner join matable2 t2 on t2.xxxx = t0.xxxx " +
                 "inner join matable3 t3 on t3.xxxx = t0.xxxx " +
                 "inner join matable4 t4 on t4.xxxx = t0.xxxx " +
                 "where t0.num ='" + sirens[a] + "'";
 
                MySqlCommand cmd = new MySqlCommand(marequete, conn);
                  monreader = cmd.ExecuteReader();
 
                if (monreader.Read())
                {
                    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;
					...............
 
 
                }
                else
                {
                    ws.Cells[a, 2] = sirens[a];//si ko, dans mon fichier excel je ne met que l'identifiant
 
                }
                   mabarre.PerformStep(); //je rempli ma barre
                   monreader.Close();
 
            }//fin du for
                
 
			
			
            ws.SaveAs(repexc, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
            xla.Quit();
 
        }
 
 
 
    }//fin méthode

comment ça se fait que le logiciel plante si c'est des fichiers plus lourds ?

N'y a t-il pas moyen d'optimiser mon code pour le rendre plus efficace et est ce que je m'y prend bien dans ma façon de requéter?
merci à vous.
 


Windows / Chrome 103.0.0.0

25 réponses

Résumé de la discussion

Une application Windows Forms lit un fichier et extrait des SIREN toutes les 14 lignes, puis interroge la base pour chaque Siren et écrit les résultats dans un fichier Excel. En petit fichier, cela fonctionne, mais avec environ 50 000 lignes l’opération se fige et ne poursuit pas, malgré une progression lente et visible. Les conseils évoquent l’optimisation: ne pas charger tout le fichier en mémoire, ne pas interroger ligne par ligne via une requête par Siren, et envisager une approche par lot ou OpenXML. La meilleure réponse propose une étape de peuplement via la BDD après prétraitement, avec une méthode paramétrée et une gestion appropriée des connexions pour les gros jeux de données.

Bobot (l’IA à votre service)
  1. bonjour ,

    pour information, le problème a été résolu.

    J'ai modifié ma requete, en laissant mon for, puis au lieu de faire un "If reader.read" j'ai mis un while.
     

    0
    1. Merci pour vos retour.

      J'ai donc crée le post vers le lien suivant : https://forums.commentcamarche.net/forum/affich-37651558-probleme-base-de-donnees-as400-vers-mysql?uDwj2arQVVRrMcAP3dU5SqMypBdnqhBi9HU2-6mDoWI

      Comme l'évoque yg_be, je pense qu'il vaudrait mieux procéder à un export propre des données, avec les liens entre chaque table, car dans le post j'ai mis la structure des tables ( issu de mysql) mais on ne peut rien utiliser comme clé primaire techniquement ..
       

      merci

      0
      1. Modérateur

        Bonjour

        Comme l'a déjà suggéré yg_be https://forums.commentcamarche.net/forum/affich-37644815-c-mysql-programme-trop-long-a-s-executer?page=1#25

        Il serait préférable de créer une nouvelle discussion propre à cette problématique.

        À noter que dans AS 400 il existe bien des liens entre chaque table...

        Si le but est de remplacer l'as400 par une base de données mysql, je doute qu'il soit nécessaire d'y rajouter des colonnes superflues telles qu'un ID auto incrémenté. Les données présentes dans l'export devraient se suffire à elles-mêmes..

        Il faudrait donc nous montrer l'intitulé des colonnes de chaque export... Et déterminer le lien entre chacun d'eux. Une colonne code, une colonne siret.. bref les données communes entre chaque fichier.

        De là, tu pourras concevoir le MCD de tes tables à créer sous mysql.


        0
        1. Bonjour à vous,

          merci pour ce retour. Tu as totalement raison, c'est un export brut de données sans les liens.

          L'export s'est fait d'un systeme as400 et on a créé une base mysql car l'as400 était destiné à ne plus être utilisé.

          Tout Le problème est là. Effectivement j'ai quelques connaissance en base de données, pendant à peu près 3 ans et plus , j'ai fais beaucoup du sql, du requetage, donc je m'y connais un peu, seulement pour ce projet là, on m'a mis à disposition une base de données (export brut) et apres c'est debrouille toi avec ça ( c'est comme faire une tarte au sucre, sans sucre , bref ).

          Voila pourquoi, nous avons créé une base de données prep, pour que je travaille dessus, et c'est là que j'ai créé mes colonnes id, mais il n'y a aucun lien logique entre les tables, car la colonne est juste en autoincremant, exemple :

          table 1: 50 lignes donc dans la colonne t1.id les numeros vont de 1 à 50

          table 2 : 120 000 lignes : donc t2.id les numeros vont de 1 à 120 000.

          Le seul moyen ( dite moi si je me trompe pas) est d'avoir un export avec les liens entre chaque table ? 

          Est il possible également d'un coup de baguette magique de palier à ce problème ? j'ai un doute sur la réponse, mais je pense que ça sera non, mais j'aimerais avoir confirmation.

          Mreci beaucoup 

          0
          1. Contributeur Ambassadeur

            Il est nécessaire d'avoir dans l'export une information qui peut servir de liens ou peut servir à recréer les liens.

            Soit via un nouvel export, soit en le découvrant dans l'export déjà fait.

            1
        2. Comme je l'ai écrit plus haut, je ne fais quasiment jamais de BDD, et j'ajoute que les rares fois où j'en fait elles sont peu volumineuses et les requêtes sont simples.

          Je vais donc déplacer le sujet dans le forum BDD


          0
          1. 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 ^

            0
            1. Contributeur Ambassadeur

              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.

              1
          2. merci c'est super gentil :) 

            0
            1. 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.


              0
              1. 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 :)

                0
                1. Contributeur Ambassadeur

                  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?

                  0
              2. 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");

                1
                1. 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("========================");
                          }

                  0
                  1. 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)


                    0
                    1. 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


                      0
                      1. Fais ce même test de ton coté, sur un gros fichier.

                        Et s'il fonctionne note le temps d'exécution

                        0
                    2. 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". 


                      0
                      1. 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 


                        0
                        1. 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.

                          0
                          1. 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.

                            0
                            1. 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

                              0
                              1. 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 :

                                0
                                1. 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.


                                  0
                                  1. 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?

                                    1
                                • 1
                                • 2