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 :

[3.5] Lecture de données en mode déconnecté [Fait]


Sujet :

C#

  1. #1
    Membre habitué Avatar de thelpi
    Profil pro
    Inscrit en
    décembre 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations forums :
    Inscription : décembre 2007
    Messages : 217
    Points : 156
    Points
    156
    Par défaut [3.5] Lecture de données en mode déconnecté
    Bonjour à tous,

    je travaille sur un projet c#/sql server. Je souhaite modifier la manière dont le programme fonctionne pour passer en mode déconnectée.

    Voici un résumé du code que j'utilisais jusque la (qui marche très bien) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    using (SqlConnection c = new SqlConnection("ma_chaine"))
    {
    	c.Open();
    	SqlCommand cmd = c.CreateCommand();
    	cmd.CommandText = "select usr_id, usr_email, cat_id from client, categorie where cat_id=usr_cat_id";
     
    	SqlDataReader rd = cmd.ExecuteReader();
     
    	while(rd.Read())
    	{
    		UneMethodeQuelconque(rd.GetInt32(0), rd.GetString(1), rd.GetInt16(2));
    	}
    }
    Mon problème, c'est que la procédure à l'intérieur du while est longue, donc je me suis dit qu'en remplaçant le DataReader par un objet déconnecté, je soulagerais le serveur sur lequel j'effectue mes requêtes.

    Le souci, c'est que je ne comprend pas grand chose au mode déconnecté, après avoir épluché 15 articles msdn...

    J'arrive pour le moment à créer une DataTable, censé contenir les mêmes informations que le DataReader, mais après j'aimerais faire des choses simples du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    maDataTable.Rows[0].GetValue(0)
    mais malheureusement ça n'a aucun sens ( ça à du sens pour moi ^^ ), je n'arrive pas à lire les infos de ma table...

    Merci pour votre aide!

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : février 2004
    Messages : 19 875
    Points : 39 743
    Points
    39 743

  3. #3
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    avril 2007
    Messages
    14 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : avril 2007
    Messages : 14 012
    Points : 24 775
    Points
    24 775
    Par défaut
    je ne crois pas qu'il soit possible de faire du mode connecté en .net, donc tu es en mode déconnecté depuis le début

    le datareader fait du mode déconnecté, les datasets et autre utilise un datareader ...


    ce que tu cherches peut etre c'est un backgroundworker
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : février 2004
    Messages : 19 875
    Points : 39 743
    Points
    39 743
    Par défaut
    Citation Envoyé par sperot51 Voir le message
    je ne crois pas qu'il soit possible de faire du mode connecté en .net, donc tu es en mode déconnecté depuis le début

    le datareader fait du mode déconnecté, les datasets et autre utilise un datareader ...

    Ben c'est nouveau ça... essaie de débrancher le cable réseau après un ExecuteReader, et de lire le DataReader... je te parie que ça marche pas ! (du moins avec des SGBD comme SQL Server, Oracle, ou MySQL)

    Un DataReader correspond à un curseur sur la BDD, et chaque appel à Read fait avancer le curseur. Heureusement que ça marche comme ça d'ailleurs, parce que sinon, le jour où tu dois traiter les résultats d'une requête qui renvoie 1 milliard de lignes, t'as intérêt à avoir un max de RAM

  5. #5
    Membre éclairé
    Avatar de Eric Berger
    Homme Profil pro
    Développeur .NET
    Inscrit en
    octobre 2002
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : octobre 2002
    Messages : 346
    Points : 663
    Points
    663
    Par défaut
    Je ne pense pas que ce que tu souhaites faire soulage la charge serveur. Tu auras juste plus de charge sur moins de temps.

    Néanmoins, si tu souhaites charger toutes tes données avant d'appliquer la logique, je te conseilles soit:
    • de stocker le résultat dans un datatable
    • de stocker le résultat dans des objets métier "client" dans une collection (dans un premier while)

    Et ensuite de parcourir l'objet contenant les résultats (DataTable ou Collection).

    Si c'est pas clair, je peux te donner des exemples.

    Eric

  6. #6
    Membre habitué Avatar de thelpi
    Profil pro
    Inscrit en
    décembre 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations forums :
    Inscription : décembre 2007
    Messages : 217
    Points : 156
    Points
    156
    Par défaut
    Merci pour vos réponses.

    J'arrive à lire tant bien que mal ma DataTable, mais ça me gêne de devoir faire
    des choses dans ce genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    dataRows.Rows[1]["usr_name"].ToString()
    Convert.ToInt32(dataRows.Rows[1]["usr_id"])
    à la place de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    dataReader.GetString(1);
    dataReader.GetInt32(1);
    Cependant, je ne fait que survoler le tuto donner par tomlev pour le moment, il y'a surement un moyen d'éviter toutes ces conversions.

  7. #7
    Membre habitué Avatar de thelpi
    Profil pro
    Inscrit en
    décembre 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations forums :
    Inscription : décembre 2007
    Messages : 217
    Points : 156
    Points
    156
    Par défaut
    Concernant la charge serveur, c'est un point essentiel de mon application.

    Sachant que la lecture du DataReader et les traitements qui en découlent peuvent prendre un temps conséquent, je pensais (peut être à tort) que le temps de chargement de la DataTable sur le serveur était ensuite compensée largement pendant le traitement qui suit.

    De plus, tout ça doit être fait le plus vite possible, il me faut déterminer également la méthode la plus rapide pour charger et lire les données...

    Je ne sais pas si je suis très clair, je peux apporter des précisions si besoin.

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : février 2004
    Messages : 19 875
    Points : 39 743
    Points
    39 743
    Par défaut
    Citation Envoyé par thelpi Voir le message
    ça me gêne de devoir faire des choses dans ce genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    dataRows.Rows[1]["usr_name"].ToString()
    Convert.ToInt32(dataRows.Rows[1]["usr_id"])
    à la place de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    dataReader.GetString(1);
    dataReader.GetInt32(1);
    Il suffit de créer un DataSet typé, à l'aide du designer.
    Tu pourras faire des trucs du genre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    foreach (UserRow u in dataSet.User)
    {
        int id = u.usr_id;
        string nom = u.usr_name;
        ...
    }

  9. #9
    Membre habitué Avatar de thelpi
    Profil pro
    Inscrit en
    décembre 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations forums :
    Inscription : décembre 2007
    Messages : 217
    Points : 156
    Points
    156
    Par défaut
    Mon objectif, c'est aussi de simplifier ma manière d'accéder aux données, en utilisant systématiquement cette méthode:

    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
    48
    49
     
    public static DataTable ExecReader(string query, List<DbParam> prms)
            {
                int attemps = 0;
                DataTable results = new DataTable();
     
                while (attemps > 5)
                {
                    using (IDbConnection c = DataProviderFactory.GetInstance().GetSqlConnection())
                    {
                        try
                        {
                            c.Open();
                            IDbCommand cmd = c.CreateCommand();
                            cmd.CommandText = query;
                            cmd.CommandTimeout = 180;
                            AddParamsAndValues(cmd, prms);
     
                            IDataAdapter adpt = DataProviderFactory.GetInstance().GetAdapter(cmd);
                            DataSet dts = new DataSet();
                            adpt.Fill(dts);
                            results = dts.Tables[0];
     
                            attemps = 5;
                        }
                        catch (SqlException e)
                        {
                            if (e.Number == 1 || e.Number == 17142)
                            {
                                if (attemps < 5)
                                {
                                    attemps++;
                                    System.Threading.Thread.Sleep(10000);
                                }
                                else
                                    throw new Exception("La connexion au serveur a échoué malgré 5 tentatives.");
                            }
                            else
                                throw e;
                        }
                        catch
                        {
                            throw new Exception("Une erreur de type inconnue est survenue.");
                        }
                    }
                }
     
                return results;
            }
    de plus, le schéma que j'ai présenté dans mon premier post, il me sert à l'heure actuelle dans environs 180 classes différentes, ayant chacune une requête différente.
    Créer maintenant une DataTable personnalisé pour chacune, ça me parait irréalisable...

    A moins que tu ai une idée de "fabrique" de DataTable perso?

  10. #10
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : février 2004
    Messages : 19 875
    Points : 39 743
    Points
    39 743
    Par défaut
    OK...
    Dans ce cas, tu peux toujours utiliser Linq to DataSets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    DataTable users = ExecReader(...);
     
    foreach (DataRow u in users)
    {
        int id = u.Field<int>("usr_id");
        string nom = u.Field<string>("usr_name");
        ...
    }
    C'est un peu moins compact que GetInt32 ou GetString, mais il n'y a plus de cast... et en plus tu utilises le nom des champs et non leur numéro, ce qui est quand même plus pratique
    D'ailleurs, si tu préfères, tu peux toujours définir tes propres méthodes d'extension GetInt32, GetString, etc pour la classe DataRow

    EDIT: en fait je pense à un autre truc, qui te permettrait en plus de ne quasiment pas modifier ton code : la méthode DataTable.CreateDataReader renvoie un DataTableReader, qui hérite de DbDataReader... donc tu pourrais utiliser ce reader à la place de celui que tu obtenais via DbCommand.ExecuteReader. Ca permettrait de faire abstraction du fait que tu sois en mode connecté ou déconnecté

  11. #11
    Membre habitué Avatar de thelpi
    Profil pro
    Inscrit en
    décembre 2007
    Messages
    217
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Deux Sèvres (Poitou Charente)

    Informations forums :
    Inscription : décembre 2007
    Messages : 217
    Points : 156
    Points
    156
    Par défaut
    Yes

    ça ça m'a l'air parfait par rapport à mon programme initial. Un grand merci !

    concernant les performances, je suis toujours indécis par contre, si tu a un article style compte-rendu de benchmark sur le sujet, ça m'intéresse grandement...

  12. #12
    Membre éclairé
    Avatar de Eric Berger
    Homme Profil pro
    Développeur .NET
    Inscrit en
    octobre 2002
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : octobre 2002
    Messages : 346
    Points : 663
    Points
    663
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    foreach (DataRow row in tonDataTable.Rows)
    {
       string maRef = row["usr_name"] as String;
       int maRefInt = Convert.ToInt32(row["usr_id"])
    }
    Effectivement, pour les types autres que string c'est pas formidable, m'enfin c'est pas horrible non plus.

  13. #13
    Membre éclairé
    Avatar de Eric Berger
    Homme Profil pro
    Développeur .NET
    Inscrit en
    octobre 2002
    Messages
    346
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Suisse

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : octobre 2002
    Messages : 346
    Points : 663
    Points
    663
    Par défaut
    oublie mon message, la syntaxe de tomlev est bien plus mieuxment bien.

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : avril 2007
    Messages : 14 012
    Points : 24 775
    Points
    24 775
    Par défaut
    Citation Envoyé par tomlev Voir le message

    Ben c'est nouveau ça... essaie de débrancher le cable réseau après un ExecuteReader, et de lire le DataReader... je te parie que ça marche pas ! (du moins avec des SGBD comme SQL Server, Oracle, ou MySQL)

    Un DataReader correspond à un curseur sur la BDD, et chaque appel à Read fait avancer le curseur. Heureusement que ça marche comme ça d'ailleurs, parce que sinon, le jour où tu dois traiter les résultats d'une requête qui renvoie 1 milliard de lignes, t'as intérêt à avoir un max de RAM
    oui et non

    le vrai mode connecté, du moins c'est ce que j'ai cru comprendre c'est de pouvoir faire des curseurs dans les 2 sens et d'avoir les modifs en temps réel, comme il était possible avec dao par exemple (curseurs optimistes et autre...)

    avec le datareader, si tu attends 2 minutes avant de faire .read et que quelqu'un modifie pendant ce temps là, je pense que tu n'as pas les modifs ...
    que le cable réseau soit déconnecté n'a rien à voir la dedans, sinon le mode déconnecté ne pourrait pas exister, vu qu'il y aurait forcément connexion
    donc je ne pense pas que ca soit "connexion" dans ce sens là
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  15. #15
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Paris (Île de France)

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

    Informations forums :
    Inscription : février 2004
    Messages : 19 875
    Points : 39 743
    Points
    39 743
    Par défaut
    Citation Envoyé par sperot51 Voir le message
    avec le datareader, si tu attends 2 minutes avant de faire .read et que quelqu'un modifie pendant ce temps là, je pense que tu n'as pas les modifs ...
    Ben non... puisque les données auraient été modifiées après l'ouverture du curseur, il ne faut pas que tu récupères les modifs ! sinon tu risques de récupérer des lignes qui ne correspondent plus aux critères de ta clause WHERE...

Discussions similaires

  1. listbox lié a une base de données en mode déconnecté
    Par Seth_75 dans le forum Windows Forms
    Réponses: 3
    Dernier message: 15/05/2008, 19h45
  2. Réponses: 2
    Dernier message: 08/01/2008, 06h07
  3. [FLASH MX2004] [XML] Lecture de données XML
    Par ZiT dans le forum Flash
    Réponses: 1
    Dernier message: 12/07/2005, 11h51
  4. [JList] Lecture des données sauvegardées dans un fichier
    Par Myogtha dans le forum Composants
    Réponses: 7
    Dernier message: 10/06/2004, 21h05
  5. lecture de données a partir de fichier
    Par sana dans le forum MFC
    Réponses: 5
    Dernier message: 21/01/2004, 12h57

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