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 :

[C#/SQL] Traitement Recordset de manière asynchrone Async/Await


Sujet :

C#

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut [C#/SQL] Traitement Recordset de manière asynchrone Async/Await
    Bonjour ,

    J'ai dans une Form, une ComboBox qui, lors d'un clic sur celle ci, effectue une requête pouvant s'avérer longue. C'est pourquoi j'aimerais passer la main à l'UI le temps que cette requête s'effectue. J'ai essayé d'utilisé Async et Await mais impossible de trouver la bonne combinaison, sachant que j'ai comme erreur "Impossible d'attendre ADODB.Recordset" .

    Voici mon code en synchrone :

    -Code du trigger sur la CB :
    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
     
            private void CBBat_DropDown(object sender, EventArgs e)
            {
                String requete;
                String connect;
                ADODB.Recordset rs = new ADODB.Recordset();
     
                  if (this.CBBat.Items.Count == 0) 
                    {
                            connect = "chaine de connexion";
                            requete = "Ma requete";
                            try
                            {
     
                                rs = ReqBDD(connect, requete, 15);
                                if (rs.EOF == false)
                                {
                                    rs.MoveFirst();
                                    while (rs.EOF == false)
                                    {
                                        if ((Convert.ToString(rs.Fields["Champ1"].Value)) != String.Empty) { this.CBBat.Items.Add(rs.Fields["Champ1"].Value); }
                                        rs.MoveNext();
                                    }
     
                                }
                                rs.Close();
                            }
                            catch
                            {
                                MessageBox.Show("erreur");
                            }
     
                     }
            }
    Et voici le code de la fonction ReqBDD :

    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
     
            private ADODB.Recordset ReqBDD(String connect, String requete, int TimeOut)//Fonction ReqBDD
            {
                ADODB.Recordset rs = new ADODB.Recordset();
                try
                {
                    ADODB.Connection cn = new ADODB.Connection();
     
                    cn.ConnectionString = connect;
                    cn.ConnectionTimeout = TimeOut;
                    cn.CommandTimeout = TimeOut;
                    cn.Open(connect, "", "", -1);
     
                    rs.ActiveConnection = cn;
                    rs.Open(requete, cn, ADODB.CursorTypeEnum.adOpenStatic, ADODB.LockTypeEnum.adLockBatchOptimistic, 1);
                }
     
                catch (Exception ex)
                {
                    MessageBox.Show("Erreur SQL avec l'exception : " + ex);
                }
     
                    return rs;
            }
    L'idée est d'exécuter la fonction ReqBDD de manière asynchrone, comment pourrais-je adapter ce code avec Async et Await ?

    Merci d'avance et bonne journée.

  2. #2
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    ADODB.Recordset C'était du temps d'ASP et de VB6 qu'on utilisait ça, ou encore dans les macro Office... Il faut revoir ton code pour utiliser ADO.NET. Je te laisse chercher il y a plein de tutoriaux sur le net...
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    En fait, cette appli est un portage d'un code VBA, je ne connaissais pas ADO.NET je vais regarder ça . Est t'il possible d'effectuer des requêtes asynchrones avec ADO.NET ?

  4. #4
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Ah ok ça explique pourquoi tu utilisais encore ça

    Sinon oui ADO.NET supporte Async/Await, voici une bonne ressource à ce sujet : Using SqlDataReader’s new async methods in .Net 4.5 (Part 1) avec des exemples ici : Using SqlDataReader’s new async methods in .Net 4.5, Part 2
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    Bonjour, j'ai adapté mon code précédent en utilisant un DataSet plutôt qu'ADODB.RecordSet. J'utilise un DataSet et non un SqlDataReader car je veux stocker les résultats en mémoire, voici ce que ça donne :

    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
     
      if (this.CbBat.Items.Count == 0)
                {
                    String connect, requete, table;
     
                    connect = "Chaine de connection";
                    requete = "ma requete";
                    table = "Ma table";
     
                    DataSet ds = new DataSet();
                    ds = Req_BDD(connect, requete, table);
     
                    foreach (DataRow row in ds.Tables[0].Rows)
                    {
                        if (Convert.ToString(row[0]) != String.Empty) { this.CbBat.Items.Add(row[0]); }
                    }       
                }
    Et voici la fonction ReqBDD :

    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
     
           private DataSet Req_BDD(String connect, String requete, String table)
            {
     
                SqlConnection connexion = new SqlConnection();
                connexion.ConnectionString = connect;
     
                SqlCommand selectCommand = new SqlCommand();
                selectCommand.Connection = connexion; 
                selectCommand.CommandText = requete;
     
                SqlDataAdapter adapter = new SqlDataAdapter(selectCommand); 
                DataSet data = new DataSet(); 
     
                try
                {
                    connexion.Open(); 
                    adapter.Fill(data, table); 
                    Thread.Sleep(7000); //met en pause le processus
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
     
                finally
                {
                    connexion.Close();
                }
     
                return data;
            }
    Avec ADO.Net tout fonctionne très bien . J'ai fait thread.sleep pour tester le fonctionnement synchrone. L'idée maintenant est de pouvoir faire une requête de manière Asynchrone c'est à dire de redonner la main à l'UI le temps que la requête s'effectue et que la mise à jour de la combobox soit effectué.
    D'après les liens donné plus haut, je n'ai pas tout compris le fonctionnement surtout avec un DataSet, il y aurait il une manière simple d'arriver à faire les requête de manière asynchrone ?

    Bonne journée.

  6. #6
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Normalement il suffit juste d'adapter la signature de ta méthode :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    private async TaskResult<DataSet> Req_BDD(String connect, String requete, String table)
    Et pour l'appel :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    ds = await Req_BDD(connect, requete, table);
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    J'y suis presque grace à vous , voilà ce que ça donne :

    Code C# de l'event sur ma comboBox

    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
     
            private async void CbBat_DropDownOpened(object sender, EventArgs e)
            {
                if (this.CbBat.Items.Count == 0)
                {
                    String connect, requete, table;
     
                    connect = "Chaine de connexion";
                    requete = "Ma requete";
                    table = "Ma table";
     
                    DataSet ds = new DataSet();
                    ds = await Req_BDD(connect, requete, table);
     
                    foreach (DataRow row in ds.Tables[0].Rows)
                    {
                        if (Convert.ToString(row[0]) != String.Empty) { this.CbBat.Items.Add(row[0]); }
                    }
                }
            }
    Et la méthode ReqBDD :

    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
     
            private async Task<DataSet> Req_BDD(String connect, String requete, String table)
            {
     
                SqlConnection connexion = new SqlConnection();
                connexion.ConnectionString = connect;
     
                SqlCommand selectCommand = new SqlCommand();
                selectCommand.Connection = connexion; 
                selectCommand.CommandText = requete;
     
                SqlDataAdapter adapter = new SqlDataAdapter(selectCommand); 
                DataSet data = new DataSet(); 
     
                try
                {
                    connexion.Open(); 
                    adapter.Fill(data, table); 
                    Thread.Sleep(7000); //met en pause le processus
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    connexion.Close();
                }
                return data;
            }
    Met ça ne change rien, de plus j'ai comme avertissement dans la méthode ReqBDD :"Avertissement, Cette méthode async n'a pas d'opérateur 'await' et elle s'exécutera de façon synchrone. Utilisez l'opérateur 'await' pour attendre les appels d'API non bloquants ou 'await Task.Run(…)' pour effectuer un travail utilisant le processeur sur un thread d'arrière-plan".

    Désolé du dérangement :S. Mais on y est presque

  8. #8
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    La méthode CbBat_DropDownOpened ne doit pas être marquée comme async puisqu'il s'agit d'un évènement. Il vaut mieux mettre ta DropDownList dans un UpdatePanel je pense.
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    Bonjour ,

    Pourtant d'après ce lien une opération asynchrone est exécutée sur l'event d'un bouton .

  10. #10
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Points : 9 743
    Points
    9 743
    Billets dans le blog
    3
    Par défaut
    Erf oui au temps pour moi, j'ai écrit des bêtises et me suis emmêlé les pinceaux avec ton code dans mon dernier message

    Donc dans Req_BDD, il faut lancer le chargement du dataset en asynchrone. Au lieu de faire :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    adapter.Fill(data, table);
    Il faudrait faire :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    await Task.Run(() => adapter.Fill(data, table));
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    Citation Envoyé par DotNetMatt Voir le message
    Erf oui au temps pour moi, j'ai écrit des bêtises et me suis emmêlé les pinceaux avec ton code dans mon dernier message

    Donc dans Req_BDD, il faut lancer le chargement du dataset en asynchrone. Au lieu de faire :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    adapter.Fill(data, table);
    Il faudrait faire :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    await Task.Run(() => adapter.Fill(data, table));
    Ne t'inquiète pas c'est vrai que c'est pas si facile non plus. Effectivement j'essaye de rendre asynchrone la méthode adapter.Fill mais je n'y arrive pas, comment l'adapter avec "Await Task.run() " ?
    Merci en tout cas il ne doit pas manquer grand chose.

  12. #12
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    183
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 183
    Points : 89
    Points
    89
    Par défaut
    C'est bon ça marche voici le code source pour ceux que ça interesserais :

    Code du bouton insérant les éléments de la requête dans une comboBox

    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
     
           private async void BPGet_Click(object sender, RoutedEventArgs e)
            {
                if (this.CbBat.Items.Count == 0)
                {
                    String connect, requete, table;
     
                    connect = "Chaine de connexion";
                    requete = "Ma requete";
                    table = "[OF]";
     
                    Task<DataSet> reqBDD = Req_BDD(connect, requete, table);
                    DataSet ds = new DataSet();
                    ds = await reqBDD;
     
                    foreach (DataRow row in ds.Tables[0].Rows)
                    {
                        if (Convert.ToString(row[0]) != String.Empty) { this.CbBat.Items.Add(row[0]); }
     
                    }
                }
            }
    Puis le code de la fonction ReqBDD :

    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
     
            private async Task<DataSet> Req_BDD(String connect, String requete, String table)
            {
     
                SqlConnection connexion = new SqlConnection();
                connexion.ConnectionString = connect;
     
                SqlCommand selectCommand = new SqlCommand();
                selectCommand.Connection = connexion;
                selectCommand.CommandText = requete;
     
                SqlDataAdapter adapter = new SqlDataAdapter(selectCommand); 
                DataSet data = new DataSet(); 
     
                try
                {
                            await Task.Run(() => {
                                connexion.Open(); // Ouverture de la connexion
                                adapter.Fill(data, table); // Récupère les données
     
                                Thread.Sleep(7000); //met en pause le processus
                             });
     
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
     
                finally
                {    
                     connexion.Close();
                }
                return data;
            }
    Merci beaucoup en tout cas !!!

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

Discussions similaires

  1. procedure pl/sql, traitement des exceptions
    Par felosa dans le forum PL/SQL
    Réponses: 7
    Dernier message: 05/12/2007, 09h44
  2. Lancer une commande de manière asynchrone
    Par CestLudique dans le forum Administration système
    Réponses: 2
    Dernier message: 20/06/2007, 13h41
  3. [SQL] Traitement de plusieurs requêtes .SQL dans un script PHP?
    Par M4x dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 19/03/2006, 19h59
  4. [PL/SQL] Traitement de date
    Par lapartdombre dans le forum Oracle
    Réponses: 4
    Dernier message: 21/11/2005, 14h55
  5. [PL/SQL] Traitement d'un curseur dans une fonction
    Par ruda.tom dans le forum Oracle
    Réponses: 1
    Dernier message: 24/10/2005, 22h06

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