[VB6] Ecriture simultanée (MS SQL Server)

rastasponch Messages postés 27 Date d'inscription jeudi 12 août 2004 Statut Membre Dernière intervention 19 décembre 2009 - 30 juin 2006 à 14:49
rastasponch Messages postés 27 Date d'inscription jeudi 12 août 2004 Statut Membre Dernière intervention 19 décembre 2009 - 10 juil. 2006 à 10:20
Bonjour à tous,

Je développe actuellement sous VB6 et accéde une base de données MS SQL Server via ADO. Mon problème est le suivant : lors de l'écriture (ou mise à jour) je souhaiterai bloquer l'accès en lecture pour les autres utilisateurs..

J'ai compris (bien que difficilement et manifestement pas suffisamment) les systèmes de verrouillage mis en place par ADO.
J'utilise un cusreur serveur (CursorLocation AdUseServer) et un verrou de type Pessimiste (LockType AdLockPessimistic)

Quel est le code à récupéré par l'erreur soulevé ? ?
Je ne trouve pas de moyen de m'en sortir...merci pour votre aide !
A voir également:

6 réponses

cs_pluplu Messages postés 615 Date d'inscription mercredi 18 décembre 2002 Statut Membre Dernière intervention 4 juillet 2012
30 juin 2006 à 19:52
En mode Pessimiste le premier utilisateur qui accède au données en modification bloque l'accès de celles-ci. En mode Optimiste c'est seulement lors de l'update que le blocage d'accès au données est fait ce qui réduit le temps de monopolisation de celles-ci, donc la première méthode est plus sure mais pénalisante pour les autres utilisateurs, la seconde est plus souple mais plus exposée au conflit d'accès concurant. Il faut faire un choix au cas par cas et quelque fois ajouter un peu de code pour palier à l'un ou l'autre de ces problèmes
0
rastasponch Messages postés 27 Date d'inscription jeudi 12 août 2004 Statut Membre Dernière intervention 19 décembre 2009
2 juil. 2006 à 11:14
Bonjour pluplu et merci de ta réponse.

Après avoir fait quelques tests, je pense utilisé le blocage pessimiste dans la plupart des programmes ou l'ajout / modification d'enregistrement est autorisé. Or j'aurais souhaité affiché un message du style "Vous ne pouvez lire cette enregistrement, un autre utilisateur cherche à le modifier actuellement"...
Savez-vous comment je peut savoir qu'un accès concurrant à lieu à ce moment ?
J'ai essayé d'utilisé la méthode .EditMode, malheureusement elle génére quoi qu'il arrive une erreur.
Je sais qu'il s'agit d'un cas d'école et qu'il est très rare que 2 personnes modifie simultanément la même donnée, toutefois c'est un test à faire pour être optimale !

Merci d'avance
0
cs_pluplu Messages postés 615 Date d'inscription mercredi 18 décembre 2002 Statut Membre Dernière intervention 4 juillet 2012
2 juil. 2006 à 19:32
Voici un petit exemple en utilisant le retour d'erreur d'un contrôle ADODC

Private Sub Retrieve_User()
Dim Userlock As Boolean 'détermine si le profil est suspendu


On Error GoTo Errorhandler
Init_DB 'Initialise les infos pour ouvrir la base de donnée
Sql_Str = "Select * from Users Where Users.Ident like '" & Rtext_Ident.Text & "'"

With Adodc1
.ConnectionString = sConnection
.RecordSource = Sql_Str
End With
Adodc1.Refresh
' Si le user existe, donne son dernier accès
Lbl_Status = "Dernière Connection, le " & Adodc1.Recordset.Fields![Last_Access].Value
' On vérifie si le compte utilisateur n'est pas suspendu !!
If Userlock Adodc1.Recordset.Fields![Userlock].Value False Then Err.Raise vbObjectError + 513

Exit Sub

Errorhandler:

Select Case Err.Number

Case vbObjectError + 513 'le compte User est suspendu
Rtext_Ident.Text = ""
Lbl_Titre = "Ident suspendue!"
Lbl_Texte = "Votre Identification est Suspendue," _
& "en cas de besoin contactez votre Administrateur système."
Rfra_Erreur.Visible = True
Case 3021 'Ident incorrect
Rtext_Ident.Text = ""
Lbl_Titre = "Ident incorrect!"
Lbl_Texte = "Votre Identification est innexistante ou incorrecte," _
& "en cas de besoin contactez votre Administrateur système."
Rfra_Erreur.Visible = True
Case -2147217843 'La base est ouverte en mode exclusif
Rtext_Ident.Text = ""
Lbl_Titre = "Acces impossible"
Lbl_Texte = "La base de donnée est ouverte en mode exclusif," _
& "en cas de besoin contactez votre Administrateur système."
Rfra_Erreur.Visible = True
' Case -2147467259 'La base est en cours d'utilisation

Case Else 'Une autre erreur s'est produite
Rtext_Ident.Text = ""
Lbl_Titre = "Erreur système!"
Lbl_Texte = "Une erreure système est intervenue : " & Err.Number _
& " Désignation : " & Err.Description & ". En cas de besoin contactez votre Administrateur système."
Rfra_Erreur.Visible = True
End Select

End Sub

Je n'ai pas la liste des error code renvoyés par ADO mais celle-ci doit se trouver sur MSDN
0
rastasponch Messages postés 27 Date d'inscription jeudi 12 août 2004 Statut Membre Dernière intervention 19 décembre 2009
7 juil. 2006 à 11:14
Salut pluplu,

merci pour ton code, cela m'a aidé pour trouvé les codes d'erreurs.
Toutefois, il semble que seule l'erreur n° 3021 soit traitée au niveau de l'objet Recodset.open lorsqu'un utilisateur accède une donnée déjà en consultation par un autre utilisateur.
Après plusieurs test, je n'ai pas trouvé comment redonné la main à l'utilisateur (si ce n'est en fermant la connection puis en la ré-ouvrant aussitôt)
De plus il semblerait que le verrou ne bloque pas uniquement l'enregistrement en cours mais toute la table.

Donc ma question se transforme en : "Comment déverrouillé ?"
________________________________________
Ici je met mon code :
________________________________________

Private Sub Text1_LostFocus()

    On Error GoTo erreurecriture1

    Dim lib, stk As String

    If Text1.Text <> "" Then
        ''' Limitation de la valeur du champ
        If Val(Text1.Text) < 1 Or Val(Text1.Text) > 9999 Then
        ''' Message d'erreur
            MsgBox "Code erroné. (le code ne peut être inférieur à 0 ni supérieur à 9999)"
            Text1.Text = "": Text1.SetFocus
        Else    '# Sinon
            Text1.Text = Int(Val(Text1.Text)) 'Conversion en entier

truc:
            ''' Exécution d'une requête
            ObjetRecordset.Open "SELECT * FROM Article WHERE AR_Code=" & Text1.Text & " ;", ObjetConnection, adOpenDynamic, adLockPessimistic, -1

            ''' Récupération de l'enregistrement s'il existe déjà dans la table
            If Not (ObjetRecordset.EOF) Or (ObjetRecordset.EditMode = adEditNone) Then
                lib = ObjetRecordset("AR_Libelle")
                stk = ObjetRecordset("AR_Stock")
            End If
            ''' Si les variables n'ont pas de résultat, elle ne sont pas
            ''' affecté, donc l'article n'existe pas.
            If lib <> "" And stk <> "" Then
                Text2.Text = lib
                Text3.Text = stk
            Else
                 MsgBox "Saisir un article."                 Text2.Text "": Text3.Text ""
                 Text2.SetFocus
            End If
        End If
    End If

erreurecriture1:

    Select Case Err.Number
   
        Case 3021 'Ident incorrect
            MsgBox "Consultation impossible.", , "Erreur..."
            If ObjetRecordset.State = 1 Then
                ObjetRecordset.Close
            End If
           
            '# Marche pas
            'Set ObjetRecordset = Nothing
            'Set ObjetRecordset = New ADODB.Recordset   'Recordset pour la lecture (SELECT)

            '# Marche pas
            'ObjetRecordset.Cancel
            'ObjetRecordset.CancelUpdate
            'ObjetRecordset.CancelBatch
           
            '# Marche
            ObjetConnection.Close
            ''' Test réussite fermeture
            If ObjetConnection.State = 0 Then
                MsgBox "La base est fermée."
            End If
                       
            ObjetConnection.CursorLocation = adUseServer    'Curseur côté Serveur
            ObjetConnection.Mode = adModeWrite              'Mode Ecriture
        ''' Chaine de connexion
            ObjetConnection.ConnectionString = "Provider=SQLOLEDB.1;Data Source=EPSON\EPSON;User ID=XXXXX;Password=XXXXX;DATABASE=TEST;Net=dbnmpntw;"
        ''' Connexion via objet ADODB
            ObjetConnection.Open

            Resume truc

________________________________________

merci pour ton aide
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_pluplu Messages postés 615 Date d'inscription mercredi 18 décembre 2002 Statut Membre Dernière intervention 4 juillet 2012
9 juil. 2006 à 09:31
Salut Rastasponch

Je suis assez perplexe sur le choix de ton curseur, mais regarde les liens ci-dessous ils en disent plus long sur la chose.

http://bidou.ftp-developpez.com/Cours/VB/recordsetsADO.pdf
http://www.c2i.fr/code.asp?IDCode=1026&type=&IDCate=7&Cate=

Ceci ne me semble pas correct dans ton code, car pour savoir si un enregistrement existe ce n'est pas en testant ObjetRecordset.EOF, mais en contrôlant la propriété recordcount.

''' Récupération de l'enregistrement s'il existe déjà dans la table
If Not (ObjetRecordset.EOF) Or (ObjetRecordset.EditMode = adEditNone) Then

peut être avantageusement remplacé par:

If ObjetRecordset.recordcount < 1 then ' Si le recordset est vide alors ....
0
rastasponch Messages postés 27 Date d'inscription jeudi 12 août 2004 Statut Membre Dernière intervention 19 décembre 2009
10 juil. 2006 à 10:20
J'ai déjà lu, relu et re-relu les documents vers lesquels tu me redirige...et d'après mon analyse, ce choix de curseur (adLockPessimistic) me semble absolument appropié à la situation. En effet, il s'agit du seul curseur permettant de bloquer totalement l'accès à un enregistrement (dès sa lecture).
Dans le but de migrer de DAO vers ADO, il remplace de façon adéquat la propriété LockEdit de DAO, qui, elle, bloque l'accès dès la première lecture.

En ce qui concerne le test "If ObjetRecordset.RecordCount < 1 then", je ne vois pas l'avantage d'une telle méthode. (D'après mes tests la valeur recordcount est toujours égale à -1 avec un curseur côté server (adUseServer)). De plus ce test ne vérifie pas l'accès concurant à un enregistrement (.EditMode). A priori, tu utilise un curseur de type AdUseClient, dans ce cas comment gère tu les accès concurant ? (d'après ton code, tu dispose d'une table contenant les utilisateurs, ce qui n'est pas mon cas)

Enfin, dans le cas d'une gestion de numéro de facture, les numéros doivent se suivre (sinon gare au fisc !), comment attribué ce numéro au premier accès ? Cela ne me semble pas possible avec un curseur côté client, puisque le numéro attribué ne sera pas stocké dans la base (mais belle et bien sur le poste client), un autre utilisateur peut donc se retrouver avec le même numéro...
0
Rejoignez-nous