IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Imbrication de for


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Assistant Projet Informatique
    Inscrit en
    Janvier 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Assistant Projet Informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2014
    Messages : 16
    Par défaut Imbrication de for
    Bonjour,
    Mon problème et le suivant :

    Je veux remplir une 1ère table sql server en utilisant des données présentes dans une 2e table sql server et une 3e as400.
    Pour cela j'utilise 3 DataTables, un par table, le 3e (DT) me sert à récupérer des deux premiers les lignes que je veux insérer dans ma 1ère table.

    J'ai créer l'algo qui permet de comparer les deux 1ers DataTables en fonction des champs qui m'intéressent.
    Comme je boucle sur ces deux derniers, le temps que prend mon programme à s'exécuter est fonction du nombre de lignes concernées. Afin de réduire cela au maximum je supprime au fur et à mesure les lignes que je ne veux pas copier afin de ne pas reboucler dessus au prochain passage. Ce qui fait que je boucle sur un total de ligne d'un DataTable qui évolue. Et ce qui me pète de jolis IndexOutOfRange Exception.

    Avec le code ci-dessous, l'erreur est la suivante : Aucune ligne à la position 482.
    J'ai donc supprimé 18lignes avant que l'exception pointe le bout de son nez, j'ai donc j=482 et i=0.
    J'ai tenté un paquet de coup de Trafalgar mais rien de fonctionne.

    J'espère que mon code ne vous paraitra pas trop obscur (sinon ne vous concentrez que sur les conditions des for) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    DT = dtas.Clone();
                for (int i = 0; i < dtas.Rows.Count; i++)
                {                                                                                                                                       //on parcourt les lignes de l'AS400
                    check = false;
                    for (int j = 0; j < dtsql.Rows.Count || dtsql.Rows.Count > 0 || !check; j++)                                                        //on parcourt les lignes de SQL Server
                    {
                        if ((string)dtas.Rows[i][dtas.Columns["ORDNO"].Ordinal] == (string)dtsql.Rows[j][dtsql.Columns["SNOF"].Ordinal] &&
                            (string)dtas.Rows[i][dtas.Columns["OPSEQ"].Ordinal] == (string)dtsql.Rows[j][dtsql.Columns["SOPE"].Ordinal])                //si le couple clé primaire est identique
                        {                                                                                                                               
                            if ((string)dtas.Rows[i][dtas.Columns["OPSTC"].Ordinal] != (string)dtsql.Rows[j][dtsql.Columns["SITUATION"].Ordinal] &&
                                Convert.ToInt32((string)dtas.Rows[i][dtas.Columns["OPSTC"].Ordinal]) == 0)                                              //si la situation est différente et OPSTC = "00"
                            {                                                                                                                           
                                DT.Rows.Add(dtas.Rows[i].ItemArray);                                                                                    //on ajoute la ligne au datatable temporaire
                                dtsql.Rows.Remove(dtsql.Rows[j]);                                                                                       //et on supprime la ligne
                                check = true;
                            }
                            if ((string)dtas.Rows[i][dtas.Columns["WKCTR"].Ordinal] != (string)dtsql.Rows[j][dtsql.Columns["SPDC"].Ordinal])            //si les postes sont identiques
                            {
                                DT.Rows.Add(dtas.Rows[i].ItemArray);                                                                                    //on ajoute la ligne au datatable temporaire
                                DT.Rows[DT.Rows.Count - 1][DT.Columns["OPSTC"].Ordinal] = (string)dtsql.Rows[j][dtsql.Columns["SITUATION"].Ordinal];    //on rajoute la situation de SQL Server
                                dtsql.Rows.Remove(dtsql.Rows[j]);                                                                                       //et on supprime la ligne
                                check = true;
                            }
                            if (!check)
                            {
                                dtsql.Rows.Remove(dtsql.Rows[j]);
                                check = true;
                            }
                        }
                        else                                                                                                                            //si le couple clé primaire est différent
                        {
                            if (Convert.ToInt32(((string)dtas.Rows[i][dtas.Columns["ORDNO"].Ordinal]).TrimStart('M')) > Convert.ToInt32(((string)(dtsql.Rows[j][dtsql.Columns["SNOF"].Ordinal])).TrimStart('M')) ||
                                Convert.ToInt32(((string)dtas.Rows[i][dtas.Columns["ORDNO"].Ordinal]).TrimStart('M')) == Convert.ToInt32(((string)(dtsql.Rows[j][dtsql.Columns["SNOF"].Ordinal])).TrimStart('M')) &&
                                Convert.ToInt32(((string)dtas.Rows[i][dtas.Columns["OPSEQ"].Ordinal]).TrimStart('M')) > Convert.ToInt32(((string)(dtsql.Rows[j][dtsql.Columns["SOPE"].Ordinal])).TrimStart('M')))
                            {                                                                                                                           //si (ORDNO > SNOF) ou (ORDNO = SNOF et OPSEQ > SOPE)
                                dtsql.Rows.Remove(dtsql.Rows[j]);                                                                                       //on supprime la ligne et on passe à la suivante
                                check = true;
                            }
                        }
                    }
     
                    if (!check)                                                                                                                         //si non trouvée, on ajoute la ligne au datatable temporaire
                    {
                        DT.Rows.Add(dtas.Rows[i].ItemArray);
                    }
                }
    Merci aux courageux qui tenteront l'expérience...

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    pas lu le code, mais pour comparer des données autant laisser ça aux bases de données

    il est possible de faire des requetes sur différentes bases d'un même serveur
    et il est possible de faire des liens entres 2 serveurs (serveur lié), y compris vers un AS400

    après pour savoir s'il y a des différentes il suffit d'écrire des choses dans le genre
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    select id from table1 where id not in (select id from autrebase.table1)

    ou encore
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (select * from table 1 union select * from autrebase.table1) <> (select count(*) from table1) 
        print 'il y a au moins une différence sur une "cellule" pour table1'
    -- UNION supprime les doublons contrairement à UNION ALL<

    et selon ce que tu veux faire il y a moyen de faire des requêtes dans le genre
    c'est simple et performant
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    Membre averti
    Homme Profil pro
    Assistant Projet Informatique
    Inscrit en
    Janvier 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Assistant Projet Informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2014
    Messages : 16
    Par défaut Oui mais non...
    Citation Envoyé par Pol63 Voir le message
    pas lu le code, mais pour comparer des données autant laisser ça aux bases de données

    il est possible de faire des requetes sur différentes bases d'un même serveur
    et il est possible de faire des liens entres 2 serveurs (serveur lié), y compris vers un AS400

    après pour savoir s'il y a des différentes il suffit d'écrire des choses dans le genre
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    select id from table1 where id not in (select id from autrebase.table1)

    ou encore
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    if (select * from table 1 union select * from autrebase.table1) <> (select count(*) from table1) 
        print 'il y a au moins une différence sur une "cellule" pour table1'
    -- UNION supprime les doublons contrairement à UNION ALL<

    et selon ce que tu veux faire il y a moyen de faire des requêtes dans le genre
    c'est simple et performant
    Oui je sais tout ça mais ce n'est pas ce qui m'intéresse. Actuellement mon serveur AS400 est déclaré en tant que serveur lié dans SQL Server (je passe donc des commandes sql alimentant directement mes tables), mais j'ai des pb de perf et de gestion des erreurs. J'ai donc créé un programme censé copier le comportement de ces requêtes qui sont somme toutes fonctionnelles, mais ajoutant une couche de gestion relativement importante. Voilà pk j'utilise des DataTables, et voilà pk j'ai besoin de ce que je demande
    Le but est justement de se passer du serveur lié.

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 197
    Par défaut
    le datatable n'est pas ce qu'il y a de plus performant (c'est peut etre quand même mieux que le serveur lié) et puis c'est pas très joli à lire
    les serveurs liés sont plus performants avec des openquery que des serveur.base..table aussi mais ca peut rester plus poussif que de l'accès direct via ado.net

    plus de détails sur le fonctionnement souhaité ? (peu de colonnes à vérifier, un clé primaire intervient ? ...)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    Membre averti
    Homme Profil pro
    Assistant Projet Informatique
    Inscrit en
    Janvier 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Assistant Projet Informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2014
    Messages : 16
    Par défaut Redéfinition du problème
    Citation Envoyé par Pol63 Voir le message
    le datatable n'est pas ce qu'il y a de plus performant (c'est peut etre quand même mieux que le serveur lié) et puis c'est pas très joli à lire
    les serveurs liés sont plus performants avec des openquery que des serveur.base..table aussi mais ca peut rester plus poussif que de l'accès direct via ado.net

    plus de détails sur le fonctionnement souhaité ? (peu de colonnes à vérifier, un clé primaire intervient ? ...)
    Je n'ai peut-être pas assez clair mais mon soucis n'est pas dans la technologie mais dans la technique pure. J'ai présenté mon contexte mais en réalité c'était plus pour la forme et la compréhension globale.
    Mon seul soucis à l'heure actuelle vient simplement d'une exception (IndexOutOfRange) d'un For. Si vous jeter un œil au code peut-être que vous trouverez immédiatement d'où vient le problème. Il vient certainement des conditions de sortie de mes for imbriqués mais j'ai essayé pas mal de choses et je n'y arrive pas.
    Le reste du code est également là pour faire joli ^^
    Donc si vous le trouvez trop difficile à lire ne vous concentrez que sur les for...

  6. #6
    Membre émérite
    Homme Profil pro
    Architecte technique
    Inscrit en
    Septembre 2005
    Messages
    462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 462
    Par défaut
    Vu l'erreur que tu as, on va avoir du mal à t'aider.
    Il faut debuger...
    Tu as toutes les informations : Tu sais que tu essai de lire une ligne ou une colonne d'un tableau ou (DataTable) qui n'existe pas.

    Et personnellement tes "if" avec pleins de conditions qui utilisent des "i" des "j" et des "Ordinal", je trouve ça horrible à lire...
    Et :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    j < dtsql.Rows.Count || dtsql.Rows.Count > 0 || !check
    Hum ça veut dire quoi ?

Discussions similaires

  1. [AC-2010] Imbrication for each
    Par AidezMoiSvp dans le forum VBA Access
    Réponses: 13
    Dernier message: 16/08/2012, 15h37
  2. Imbrication FOR et IF dans VBA
    Par klemsy20 dans le forum Excel
    Réponses: 3
    Dernier message: 28/06/2011, 10h50
  3. imbrication boucle FOR
    Par ericdev67 dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 07/03/2011, 19h51
  4. Imbrication de boucles For
    Par dominos dans le forum Débuter
    Réponses: 4
    Dernier message: 03/04/2010, 17h53
  5. [XSLT] Imbrication de for-each
    Par The_Big_Lebowski dans le forum XSL/XSLT/XPATH
    Réponses: 10
    Dernier message: 12/03/2009, 17h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo