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 :

Verrouiller un enregistrement


Sujet :

C#

  1. #1
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    242
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 242
    Par défaut Verrouiller un enregistrement
    Bonjour,

    Pour accéder à ma base de données, j'utilise une connexion telle que ceci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    SqlConnexion MyConnexion = new SqlConnection();
     
    MyConnexion.ConnectionString = "Integrated security = true, intial Catalog = '" + mydatabase + "', Data source = '" + myserver + "', user = '" + myuser + "', password = '" + mypassword + "'";
     
    MyConnexion.Open();
    Aprés cela il suffit d'employer les dataCommand et les dataReaderSql.

    Mon souci est qu'il faut pour certaines données, que je verrouille l'enregistrement pour qu'aucun autre utilisateur n'y ait accés tant que l'opération n'est pas terminée.

    C'est ,entre autres, pour récupérer dans une table de compteurs, le prochain n° de commande, facture etc...

    L'idéal serait qu'avant qu'un 2eme utilisateur essaie d'accéder au même enregistrement, je puisse lui faire vérifier que celui-ci n'est pas verrouillé.

    L'opération:
    Je lis mon compteur,
    je l'incrémente
    j'enregistre le nouveau compteur,
    je ferme le DataReaderSQL

    est certes trés rapide, mais n'est pas garantie à 100%.

    Et je n'arrive pas à trouver où préciser qu'il faut verrouiller l'enregistrement.

    Merci.

  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 : 44
    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
    Par défaut
    C'est quel SGBD ? Oracle, SQL Server... ?

    Sous Oracle tu peux faire ça :

    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT a FROM b WHERE c = 1 FOR UPDATE

    Ca verrouille la ligne jusqu'à la fin de la transaction (commit ou rollback)

  3. #3
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    242
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 242
    Par défaut
    C'est SQL Server 2008.

  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 : 44
    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
    Par défaut
    Pour SQL Server, je sais pas trop comment on fait...

    Mais en fait, je vois un moyen simple d'arriver au même résultat, sans locker explicitement :

    - commencer une transaction
    - incrémenter le compteur (la ligne est bloquée jusqu'à la fin de la transaction)
    - récupérer la valeur (-1 si on veut la valeur précédente)
    - valider la transaction (commit)

    En code, ça donne quelque chose comme ça :

    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
    int value;
    using (DbTransaction transaction = connection.BeginTransaction())
    {
        using (DbCommand command = connection.CreateCommand())
        {
            command.CommandText = "UPDATE la_table SET le_champ = le_champ + 1 WHERE id = xxx";
            command.Transaction = transaction;
            command.ExecuteNonQuery();
        }
        using (DbCommand command = connection.CreateCommand())
        {
            command.CommandText = "SELECT le_champ FROM la_table WHERE id = xxx";
            command.Transaction = transaction;
            value = (int)command.ExecuteScalar();
        }
     
        transaction.Commit();
    }

  5. #5
    Membre expérimenté
    Profil pro
    Mangeur de gauffre
    Inscrit en
    Octobre 2007
    Messages
    4 413
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Mangeur de gauffre

    Informations forums :
    Inscription : Octobre 2007
    Messages : 4 413
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Pour SQL Server, je sais pas trop comment on fait...

    Mais en fait, je vois un moyen simple d'arriver au même résultat, sans locker explicitement :

    - commencer une transaction
    - incrémenter le compteur (la ligne est bloquée jusqu'à la fin de la transaction)
    - récupérer la valeur (-1 si on veut la valeur précédente)
    - valider la transaction (commit)

    En code, ça donne quelque chose comme ça :

    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
    int value;
    using (DbTransaction transaction = connection.BeginTransaction())
    {
        using (DbCommand command = connection.CreateCommand())
        {
            command.CommandText = "UPDATE la_table SET le_champ = le_champ + 1 WHERE id = xxx";
            command.Transaction = transaction;
            command.ExecuteNonQuery();
        }
        using (DbCommand command = connection.CreateCommand())
        {
            command.CommandText = "SELECT le_champ FROM la_table WHERE id = xxx";
            command.Transaction = transaction;
            value = (int)command.ExecuteScalar();
        }
     
        transaction.Commit();
    }
    +1

  6. #6
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    242
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 242
    Par défaut La bonne syntaxe
    Superbe ça marche, voici la bonne synthaxe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    SqlConnection cn = new SqlConnection();
    cn.ConnectionString = "Integrated security etc...";
     
    SqlTransaction transac = cn.BeginTransaction("REPEATABLE READ");
     
    SqlCommand dt = cn1.CreateCommand();
    dt.Transaction = transac;
    dt.CommandText = "UPDATE latable SET lechamp = lechamp + 1 WHERE etc..";
     
    dt.ExecuteNonQuery();
     
    transac.Commit();

    En fait en utilisant "UPDATE latable SET lechamp = lechamp + 1", je pense qu'on réduit tellement les risques d'erreurs, qu'ils deviennent négligeables.
    Mais autant faire solide!

    J'ai fait le test depuis 2 postes, cela fonctionne trés bien. On peut laisser le begintransaction tourner trés longtemps, en ne déclenchant le commit que par un click sur un bouton.
    le 2eme PC attend que l'enregistrement se libère pour y accéder. On est juste arrété par le délai d'attente de SQL Server.

    Merci bien.

  7. #7
    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 : 44
    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
    Par défaut
    Selon la loi de Murphy, même un risque "négligeable" n'est pas acceptable...
    S'il est possible que quelque chose aille de travers, ça arrivera tôt ou tard

    Tu devrais faire le SELECT avant de terminer la transaction ; c'est le seul moyen de t'assurer que personne d'autre n'aura modifié la valeur entre temps. Si tu fais ça, le risque ne sera pas négligeable mais nul

  8. #8
    Futur Membre du Club
    Inscrit en
    Février 2010
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Février 2010
    Messages : 3
    Par défaut
    excusez moi je prends la discussion en cours. mais à quoi sert le select dans ce cas?

  9. #9
    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 : 44
    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
    Par défaut
    Citation Envoyé par YOKOSUNO Voir le message
    excusez moi je prends la discussion en cours. mais à quoi sert le select dans ce cas?
    Il ne s'agit pas seulement d'incrémenter un compteur, mais aussi de récupérer sa valeur courante...

    Citation Envoyé par HENRYC
    C'est ,entre autres, pour récupérer dans une table de compteurs, le prochain n° de commande, facture etc...

  10. #10
    Membre éclairé
    Inscrit en
    Janvier 2005
    Messages
    242
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 242
    Par défaut
    A Tomlev,

    Il est tout à fait exact qu'il faut faire le select avant la fin de la transaction, sinon ça ne sert à rien.

    C'est un oubli de ma part.


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

Discussions similaires

  1. Verrouiller un enregistrement
    Par Pierre59 dans le forum MS SQL Server
    Réponses: 5
    Dernier message: 16/02/2007, 17h32
  2. Verrouiller un enregistrement
    Par touhami dans le forum InterBase
    Réponses: 5
    Dernier message: 15/03/2006, 11h59
  3. Verrouiller un enregistrement
    Par PAUL87 dans le forum Access
    Réponses: 32
    Dernier message: 10/12/2005, 23h15
  4. Verrouiller un enregistrement lors d'un select
    Par RamDevTeam dans le forum Bases de données
    Réponses: 5
    Dernier message: 01/11/2005, 17h20
  5. verrouiller un enregistrement - VBA/Access
    Par sebouratif dans le forum Access
    Réponses: 2
    Dernier message: 07/10/2005, 13h03

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