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

VB.NET Discussion :

Different comportement entre OleDb et SqlClient [Débutant]


Sujet :

VB.NET

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 58
    Points : 38
    Points
    38
    Par défaut Different comportement entre OleDb et SqlClient
    Bonjour à tous,
    je débute en vb .net et je croyais que le comportement de vb .net était identique avec une base Access ou une base SQL Server

    Pourtant j'ai fait le programme suivant en connection avec la base Access :
    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
     
    Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
     
            'Cette procedure met à jour le champ fld2 de la valeur du champ fld1 à laquelle on ajoute 100
            'SVP je sais qu' une seule update sql fait la meme chose sans avoir besoin de curseur
            'le but ici est justement d'utiliser un curseur
     
            Dim cnx As New OleDb.OleDbConnection    ' Dim cnx As New SqlClient.SqlConnection dans le cas où db1 est une base sql server
            Dim cmd As New OleDb.OleDbCommand
            Dim crs As New OleDb.OleDbCommand       'crs = abreviation pour curseur
            Dim drd As OleDb.OleDbDataReader        'à noter qu'il ne faut pas utiliser new pour la classe datareader qui n'a pas de constructor
     
            Dim v_fld1 As Integer                   'stocke la valeur du champ fld1 pour l'enregistrement en cours du datareader
     
            cnx.ConnectionString = My.Settings.cs_db1
            cnx.Open()
            cmd.Connection = cnx
            crs.Connection = cnx
     
            crs.CommandText = "SELECT fld1, fld2 FROM tbl1 ORDER BY fld1;"
            'le data reader permat d'obtenir un curseur et de le parcourir en avant
            drd = crs.ExecuteReader
     
            While drd.Read
                v_fld1 = drd("fld1")         'obtient la clé fld1 dans le but d'updater un seul record
                cmd.CommandText = "UPDATE tbl1 SET fld2=" & v_fld1 + 100 & " WHERE fld1=" & v_fld1 & ";"
                cmd.ExecuteNonQuery()
            End While
     
            MessageBox.Show("Petite temporisation")
            Me.Tbl1TableAdapter.Fill(Me.Db1DataSet.tbl1)
     
            drd.Close()
            cnx.Close()
     
        End Sub
    Voilà ce code fonctionne parfaitement bien, mais si maintenant je crée une base avec SQL Server, je fais un autre projet similaire au précédent en utilisant le wizard mais en choisissant une connexion sur ma base SQL au lieu de la base Access, j'adapte ensuite le code en remplaçant OleDb par SqlClient pour le namespace et OleDb par Sql pour le préfixe de Connection, Command et DataReader, et je lance le code en cliquant sur Button1

    J'obtiens alors le message d'erreur:
    There is already an open DataReader associated with this Command which must be closed first
    à l'execution de l'update (cmd.ExecuteNonQuery())

    C'est bizarre que ça marche avec OleDb et pas avec SqlClient
    Que faut-il faire pour que ça marche ? (OK je peux faire une procédure stockée mais justement j'étais en train d'apprendre comment faire sans procédure stockée)

    J'ai un autre petit problème là où j'ai mis "Petite temporisation"
    Si je ne mets pas de temporisation, soit par un messagebox ou alors par un procédure de temporisation (1/2 seconde approx.) , le datagridview n'est pas mis à jour par la valeur réelle contenue dans la table !!!!
    C'est comme si l'update se faisait dans un cache et que le fill du datagridview se faisait avant que le cache ait eu le temps de se synchroniser dans la table, ce qui explique qu'on ne visualise pas l'update (qui a bien eu lieu car je peux le vérifier avec Access)

    Merci pour votre aide

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    peut etre une erreur de copier coller
    parce que l'erreur dit qu'un DbCommand ne peut pas exécuter une requete s'il a un Reader ouvert, il faut faire reader.close quand on en a plus besoin

    après d'une manière générale un curseur c'est une très mauvaise idée
    ici ton code peut faire 3 lignes et être 1000x plus performant en connaissant le langage sql


    pour la tempo il faudrait voir si tu as le même problème avec sql server
    c'est le problème quand on utilises des assistants, ils génèrent du code et si on ne va pas le voir on ne sait pas ce que fait ce code ... en le tapant soit même on a moins de surprises
    on voit souvent ici des gens qui ont une base de données qui se réinit à chaque exécution en mode debug quand ils passent par les assistants et access
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  3. #3
    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 : 42
    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 749
    Points
    39 749
    Par défaut
    Citation Envoyé par jloois Voir le message
    C'est bizarre que ça marche avec OleDb et pas avec SqlClient
    Bah non, c'est pas étonnant au contraire... Access et SQL Server sont des SGBD complètement différents et n'ont pas les mêmes caractéristiques.

    Tu ne peux pas exécuter la même commande pour l'update pendant que tu parcours ses résultats, il faut créer une 2e commande. Access est peut-être moins strict là-dessus, mais avec SQL Server c'est obligatoire.

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    il a bien 2 commands :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    crs.ExecuteReader
    (...)
    while 
      cmd.ExecuteNonQuery
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  5. #5
    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 : 42
    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 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    il a bien 2 commands :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    crs.ExecuteReader
    (...)
    while 
      cmd.ExecuteNonQuery
    Ah oui, j'ai lu trop vite... au temps pour moi

  6. #6
    Expert éminent Avatar de Graffito
    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    5 993
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 993
    Points : 7 903
    Points
    7 903
    Par défaut
    La logique me semble poser un problème qui n'est peut-être pas apparu avec Access, c'est à dire la mise à jour de la base pendant l'exécution du DataReader.

    Une telle logique pourrait au mieux amener à lire/relire/ignorer des enregistrements ajoutés ou modifiés par les commandes de mise à jour et au pire à boucler.

    C'est probablement pourquoi SQL server interdit d'utiiser simultanément un dataReader et des commandes de modification de la table.
    " Le croquemitaine ! Aaaaaah ! Où ça ? " ©Homer Simpson

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    dans le pire des cas il faudrait une autre connexion, plutot que de la partager pour les 2 command
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 58
    Points : 38
    Points
    38
    Par défaut
    Merci pour vos réponses,

    suite aux premières je m'étais replongé dans le tuto de J.M. Rabilloud sur ADO .NET et effectivement comme l'a dit Pol63 dans sa dernière réponse il faut une autre connexion car comme c'est expliqué dans le tuto "L'objet Datareader est exclusif sur la connexion".

    Maintenant ça marche
    Ce qui m'a trompé, c'est que ça n'aurait pas du marcher avec OleDb mais ça a marché quand même (eh oui !?!)

    J'en profite pour répondre à Graffito qu'il n'y pas de problème conceptuel à parcourir des enregistrements pour les modifier dans la mesure ou le datareader est en lecture seule et en avant seulement (on pourrait aussi faire des insert ou des delete car les données ont été copiées dans le Datareader AVANT que ne commence le processus de modification)

    Je voudrais aussi polémiquer (gentiment) avec Pol63 sur les curseurs : c'est vrai que dans 90% des cas les programmeurs (surtout débutants) vont utiliser un curseur alors qu'une commande SQL suffit (comme dans mon code bebête dont le but était justement de créer puis parcourir un curseur)
    Mais il y quand même des cas où les curseurs sont nécessaires, de plus le code avec curseur est moins abstrait (moins ardu à coder) qu'une commande SQL très concise (mais dont la difficulté réside justement dans cette concision)

    Ceci étant dit, si vous avez une méthode plus élégante que mon curseur avec commande update à l'intérieur, je suis preneur.

    Pour le 2° point, je peux maintenant répondre que NON le problème n'existe pas avec SQL Server car celui-ci , je pense, ne bufferise pas les données écrites, elles vont droit dans les tables. Le problème que j'ai rencontré est je pense inhérent au moteur Jet et il faut éviter du code "time critical" avec ce moteur sous peine de s'exposer à des déconvenues (de fait j'ai déja eu des problèmes similaires avec Access)

    Merci encore à tous

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    Citation Envoyé par jloois Voir le message
    Ce qui m'a trompé, c'est que ça n'aurait pas du marcher avec OleDb mais ça a marché quand même (eh oui !?!)
    access a toujours fait ce qu'il voulait en dehors des normes de toute facon ^^

    Citation Envoyé par jloois Voir le message
    J'en profite pour répondre à Graffito qu'il n'y pas de problème conceptuel à parcourir des enregistrements pour les modifier dans la mesure ou le datareader est en lecture seule et en avant seulement
    c'est peut être un snapshot plutot ...

    Citation Envoyé par jloois Voir le message
    Je voudrais aussi polémiquer (gentiment) avec Pol63 sur les curseurs : c'est vrai que dans 90% des cas les programmeurs (surtout débutants) vont utiliser un curseur alors qu'une commande SQL suffit (comme dans mon code bebête dont le but était justement de créer puis parcourir un curseur)
    Mais il y quand même des cas où les curseurs sont nécessaires, de plus le code avec curseur est moins abstrait (moins ardu à coder) qu'une commande SQL très concise (mais dont la difficulté réside justement dans cette concision)
    polémiquons alors ^^
    il n'y a aucun cas où seul un curseur peut marcher (je m'avance peut être mais suis prêt à chercher en cas de proposition )
    de plus quand je dis 1000x plus performant sans curseur, je ne mens pas, ca dépend des cas certes mais ca peut monter à des millions de fois plus performant même
    quant à la lisibilité, tout est relatif, certes c'est un peu plus compliqué mais ca se comprend
    maitriser un langage ca passe aussi par utiliser des choses complexes, et faire un logiciel sans tenir compte des performances c'est aller droit dans le mur
    beaucoup de développeurs négligent les bases de données, et dans l'ancienne boite où j'étais, le soft marchait bien au début, et 5 ans plus tard, un clic engendrait jusqu'à 10 heures de freeze de l'appli sur une procédure stockée sql


    Citation Envoyé par jloois Voir le message
    Ceci étant dit, si vous avez une méthode plus élégante que mon curseur avec commande update à l'intérieur, je suis preneur.
    UPDATE tbl1 SET fld2= fld1 + 100 ??
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 58
    Points : 38
    Points
    38
    Par défaut
    Pol63, désolé d'abuser de ta patience mais je me suis mal exprimé
    OK bien sur je sais que dans ce cas précis on peut faire UPDATE tbl1 SET fld2= fld1 + 100
    Je voulais dire :
    Si tu veux faire un curseur ou que tu dois faire un curseur (parce qu'il n'y pas d'autre alternative) et que tu parcours ce curseur pour faire des modications (update/insert/delete) dans la même table ou dans une/des autres tables reliées, la méthode que j'ai utilisée (soit un datareader et des requêtes SQL) est-elle la/une bonne méthode ou y-a-il une autre/meilleure méthode plus qui utilise mieux la bibliothèque ?
    Par exemple avec DAO (une ancêtre) on peut utiliser une méthode similaire (c.a.d. un recordset comme curseur et des requetes SQL ou bien des instructions comme rs.fields("fld2")=mavaleur, le genre de code avec lequel tu écris une application entière sans la moindre ligne de SQL, à mon sens la 2° est moins bonne.

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    je répète qu'un curseur peut à mon sens toujours être évité
    si on ne sait pas faire autrement, le curseur doit rester sur la base de données

    si ta table contient 1000 lignes, tu vas faire 1000 aller retour réseau de lecture, et 1000 aller retour réseau d'écriture
    en laissant l'exécution et donc le curseur côté sql tu n'auras au final qu'un seul aller retour réseau (que ca soit une procédure stockée ou non, on peut mettre plusieurs requetes dans le commandtext)
    (DECLARE CURSOR pour sql server)

    ca ne sert à rien de ramener des données qui ne seront pas affichée
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  12. #12
    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 : 42
    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 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Pol63 Voir le message
    je répète qu'un curseur peut à mon sens toujours être évité
    si on ne sait pas faire autrement, le curseur doit rester sur la base de données
    Pas forcément : le traitement peut aussi dépendre de données qui n'existent pas en base...

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

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 154
    Points : 25 072
    Points
    25 072
    Par défaut
    on peut aussi lui envoyer les données qu'il n'a pas

    enfin un principe aussi c'est qu'un sgbdr n'est pas fait pour faire du calcul complexe sur les données, .net est bien plus rapide pour ca donc parfois ramener les données sera plus rapide (m'enfin il y a les sp .net aussi)
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  14. #14
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 58
    Points : 38
    Points
    38
    Par défaut
    Je ne veux pas trop insister sur pour ou contre les curseurs (tres vaste sujet)
    Mon problème est résolu, donc je vais cloturer le sujet
    Merci encore à tous

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

Discussions similaires

  1. différence de comportements entre JVM
    Par Nicaisse dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 30/08/2007, 11h41
  2. Réponses: 0
    Dernier message: 03/08/2007, 17h59
  3. Réponses: 2
    Dernier message: 20/06/2007, 10h27
  4. Réponses: 5
    Dernier message: 10/04/2007, 09h37
  5. [JavaScript] Différence de comportement entre IE et FF
    Par YAMKI dans le forum Général JavaScript
    Réponses: 6
    Dernier message: 23/02/2007, 14h33

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