1. #1
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    février 2010
    Messages
    3 061
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2010
    Messages : 3 061
    Points : 5 016
    Points
    5 016
    Billets dans le blog
    1

    Par défaut SqlDataReader.NextResult() : Comment ça marche ?

    Bonjour,

    Je tente en vain d'exécuter deux requêtes à la suite et tout récupérer dans le même SqlDataReader.

    Voici mon code :
    Code csharp : 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
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
     
            const string QUERY_STATION = @"
                select 
                    cast(st.id as smallint), 
                    st.asname,
                    st.ComAusDatum_DT,
                    st.ComAusDauer,
                    st.ComEinDatum_DT,
                    st.ComEinDauer,
                    st.szyk,
                    st.sdat,
                    id.id beaid,
                    id.fname,
                    id.vname,
                    c1.synchro,
                    c1.einstellung
                from te_isi_sta st
                left outer join te_isi_id id on id.id = st.beaid and id.loskz = 0 and id.inaktiv = 0
                left outer join te_isi_c1 c1 on c1.asquelle = 1 and c1.asziel = st.id
                where st.loskz = 0
                and st.id between @station_min and @station_max;
            ";
     
            const string QUERY_LOG = @"
                select 
                    ComStationNr, 
                    dbo.CU_CRMDate_To_Date(cast(ComDatum_DT / 1000000000 as int)), 
                    count(*), 
                    sum(ComFileSize), 
                    sum(ComAnz)
                from te_isi_c3
                where ComArt = 2
                and ComEinAus = 0
                and dbo.CU_CRMDate_To_Date(cast(ComDatum_DT / 1000000000 as int)) > dateadd(day, -31, getdate())
                and ComStationNr between @station_min and @station_max
                group by ComStationNr, dbo.CU_CRMDate_To_Date(cast(ComDatum_DT / 1000000000 as int));
            ";
     
            public CRMStationCollection()
            {
                stations = new Dictionary<short, CRMStation>();
     
                // Chargement des stations depuis la base de données
                using (SqlConnection cnx = new SqlConnection("Server=..."))
                {
                    cnx.Open();
     
                    // Chargement de toutes les stations de la base de données
                    using (SqlCommand cmd = cnx.CreateCommand())
                    {
                        cmd.CommandText = string.Concat(QUERY_STATION, QUERY_LOG);
                        cmd.Parameters.AddWithValue("station_min", STATION_MIN);
                        cmd.Parameters.AddWithValue("station_max", STATION_MAX);
     
                        // Ajout de toutes les stations à la liste
                        SqlDataReader dr = cmd.ExecuteReader(System.Data.CommandBehavior.SingleResult);
                        object[] values = new object[13];
                        /*
                            0  : Station number
                            1  : Station name
                            2  : Last out date
                            3  : Last out duration
                            4  : Last in date
                            5  : Last in duration
                            6  : Synchro perdiod
                            7  : Last synchro date
                            8  : Station's rep ID
                            9  : Station's rep first name
                            10 : Station's rep last name,
                            11 : Synchro flag
                            12 : Synchro format
                        */
                        while (dr.Read())
                        {
                            dr.GetValues(values);
     
                            if (values[8] == DBNull.Value)
                            {
                                stations[(short)values[0]] = new CRMStation((short)values[0], (string)values[1], null, (long)values[2], (int)values[3], (long)values[4], (int)values[5], (int)values[6], (int)values[7], (bool)values[11], (string)values[12]);
                            }
                            else
                            {
                                stations[(short)values[0]] = new CRMStation((short)values[0], (string)values[1], (long)values[8], (string)values[9], (string)values[10], (long)values[2], (int)values[3], (long)values[4], (int)values[5], (int)values[6], (int)values[7], (bool)values[11], (string)values[12]);
                            }
                            stations[(short)values[0]].HasRecord = true;
                        }
     
                        dr.NextResult();
     
                        values = new object[5];
                        /*
                            0 : Station number
                            1 : Date
                            2 : Number of synchronisation this date
                            3 : Total size of files this date
                            4 : Total time this date
                        */
                        while (dr.Read())
                        {
                            dr.GetValues(values);
                            if (stations.ContainsKey((short)values[0]))
                            {
                                stations[(short)values[0]].AddLog(new CRMLog((DateTime)values[1], (short)values[2], (long)values[3], (short)values[4]));
                            }
                        }
     
                        dr.Close();
                    }
                    cnx.Close();
                }

    Les deux requêtes lancées séparément retournent bien des données.

    Mais là, jamais je n'entre dans la seconde boucle...

    Comment ça se fait ?
    On ne jouit bien que de ce qu’on partage.

  2. #2
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    février 2010
    Messages
    3 061
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2010
    Messages : 3 061
    Points : 5 016
    Points
    5 016
    Billets dans le blog
    1

    Par défaut

    Nan mais quelle tanche...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    System.Data.CommandBehavior.SingleResult
    Forcément...
    On ne jouit bien que de ce qu’on partage.

  3. #3
    Candidat au Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    octobre 2017
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Congo-Kinshasa

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : octobre 2017
    Messages : 2
    Points : 3
    Points
    3

    Par défaut

    bjr, si tu veux utiliser sqldatareader,
    essaie unpeu avec ca.
    tu cree une classe nommé cnx.
    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
     
    using system.data.sqlclient;
    public class cnx
    {
     sqlconnection con=null;
    sqlcommand cmd =null;
    public sqldatareader reader =null;
    // constructeur d la classe cnx
    public cnx()
    {
    //creation d la connexion avk la base grace à l'objet con
    con = new sqlconnection(@"chaine de connexion");
    }  
    // methode permettant la lecture d données
    public void lire(string requete)
    {
    //nous ouvrons la connexion
    con.open();
    cmd = con.createcommand();
    cmd.commandtext = requete;
    reader = cmd.executereader();
    }
     
    //fermer la connexion;
    public void fermercnx()
    {
    con.close();
    }
    utilisons un datagridview.
    supposons k notre table agent a 3 champs: id, noms et age,
    dans le formulaire,

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    private void btnremp(...)
    {
    cnx cn = new cnx();
    cn.lire("select * from agent");
    datagridview1.rows.clear();
    while(cn.reader.read())
    {
    datagridview1.rows.add(cn.read[0], cn.read[1]);
    }
    cn.fermercnx();
    }
    }

  4. #4
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    février 2010
    Messages
    3 061
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2010
    Messages : 3 061
    Points : 5 016
    Points
    5 016
    Billets dans le blog
    1

    Par défaut

    Bonjour netbelt25,

    J'avoue que je ne vois pas du tout le rapport entre votre code et mon problème (résolu qui plus est).

    En effet, mon besoin concernant le parcours de plusieurs dataset au sein d'un unique appel à la base de données.

    Ici, vous me proposez un wrapper qui permet de retourner un DataReader à partir d'une simple requête, sans prendre en compte les résultats multiples.

    Accessoirement, votre code me semble risqué en terme de "fuite mémoire" (ou sur-consommation).
    En effet, la fermeture de la connexion est décorrélée de l'ouverture et lecture, ce qui peut se traduire par de multiples connexions concurrentes ouvertes en même temps sans qu'il n'y en ait besoin.
    On ne jouit bien que de ce qu’on partage.

  5. #5
    Candidat au Club
    Homme Profil pro
    Développeur .NET
    Inscrit en
    octobre 2017
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Congo-Kinshasa

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : octobre 2017
    Messages : 2
    Points : 3
    Points
    3

    Par défaut

    il semble k selon votr besoin vous voulez lire avec select, les données se trouvant dans la base, en utilisant datareader, pour aller en next sans vous vous causez d'annuis, l'utilisation une boucle parcourant les champs d table est essentielle, bon en faites je n'arrive pas à comprendre, qu'est-ce que vous voulez au juste, mais s'il s'agit d'une lecture avk un datareader, il est mieux d recuperer les données tant k l'objet datareader parcourt les données. c la moindre d choz k j peux vous dire

  6. #6
    Rédacteur/Modérateur

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    juillet 2016
    Messages
    1 419
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : juillet 2016
    Messages : 1 419
    Points : 4 783
    Points
    4 783
    Billets dans le blog
    5

    Par défaut

    Bonjour netbelt25,

    Le besoin est pourtant clairement exprimé par StringBuilder. La problématique n'est pas de lire un jeu de valeurs en utilisant un DataReader, mais d'en lire plusieurs. Dit autrement, au lieu d'avoir deux requêtes différentes, chacune avec un DataReader pour lire les données, StringBuilder souhaite exécuter les deux requêtes en même temps, et utiliser le même DataReader pour lire les résultats de la première requête, puis pour lire les résultats de la seconde requête.

    De plus, la solution que vous avez proposée est totalement bancale :
    • ne répond absolument pas à la question ;
    • est illisible (donc difficilement maintenable) ;
    • est erronée : faisant appel à des ressources implémentant IDisposable, votre classe elle-même devrait implémenter cette interface pour libérer correctement les ressources ;
    • en cas de plusieurs requêtes, vous ouvrez plusieurs fois la même connexion ;
    • pas de gestion des exceptions (si une exception survient, la connexion sous-jacente ne sera pas fermée, le datareader jamais libéré, etc...).
    François DORIN
    Consultant informatique : conception, modélisation, développement (C#/.Net et SQL Server)
    Site internet | Profils Viadéo & LinkedIn
    ---------
    Page de cours : fdorin.developpez.com
    ---------
    N'oubliez pas de consulter la FAQ C# ainsi que les cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. ToAsciiEx, comment cela marche ?
    Par mikyfpc dans le forum C++Builder
    Réponses: 2
    Dernier message: 17/02/2004, 22h39
  2. [MFC] list box : comment ça marche
    Par runn2 dans le forum MFC
    Réponses: 4
    Dernier message: 28/01/2004, 13h36
  3. [SYNEDIT] -> Comment ça marche ?
    Par MaTHieU_ dans le forum C++Builder
    Réponses: 2
    Dernier message: 18/01/2004, 20h11
  4. [TP][Turbo Vision] comment ça marche ??
    Par Costello dans le forum Turbo Pascal
    Réponses: 7
    Dernier message: 05/08/2003, 01h24
  5. [update][req. imbriquee] Comment ca marche ??
    Par terziann dans le forum Langage SQL
    Réponses: 3
    Dernier message: 11/07/2003, 13h51

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