2009-04-01 8 views
1

Le problème que je pose est la suivante:Dibs d'appel sur une ligne de tableau

J'ai une table (juste un exemple) avec les champs suivants:

ID int 
Value int 

J'ai une méthode appelée IncreaseByFive() qui effectue les opérations suivantes:

method IncreaseByFive(int ID) 
{  
    int value = GetValueFromDB(ID); 
    value = value + 5; 
    SaveValueToDB(value, ID);  
} 

Ce que je veux éviter est la situation suivante:

  1. utilisateur A appelle procédé et obtient la valeur (actuellement 5)
  2. utilisateur B appelle procédé et obtient la valeur (actuellement 5)
  3. utilisateur A augmente la valeur de 5 (maintenant 10)
  4. utilisateur B augmente la valeur par 5 (maintenant 10)
  5. utilisateur a enregistre la valeur (10)
  6. utilisateur B valeur sauve (10)

maintenant, le record a une valeur de 10 quand il aurait dû être 15.

Ce que je veux forcer est la suivante:

  1. utilisateur Une méthode appelle et obtient la valeur (actuellement 5)
  2. L'utilisateur B appelle la méthode mais doit attendre parce que A déjà appelé. (Dibs!)
  3. utilisateur A augmente la valeur (maintenant 10)
  4. L'utilisateur B attend toujours
  5. utilisateur A enregistre la valeur (enregistrement a valeur de 10)
  6. L'utilisateur B peut maintenant lire la valeur (10)
  7. l'utilisateur B augmente la valeur (15)
  8. utilisateur B enregistre la valeur

maintenant, le record a une valeur de 15, ce qui est le résultat que je cherche. J'ai résolu ce problème dans le passé en utilisant une classe statique et en plaçant un verrou sur un objet statique créé dans le constructeur de cette classe, canalisant ainsi tout le travail à travers une méthode statique, qui oblige les autres appels à attendre ligne. J'ai cependant peur que ce ne soit pas évolutif.

Je pense aussi que le plus haut niveau d'isolation (sérialisable) pour une transaction ne fera pas l'affaire non plus car il permettra la lecture à l'étape 2 de l'exemple indésirable ci-dessus.

Je suppose qu'une autre solution serait de créer ma propre table de verrouillage et d'y enregistrer les verrous, mais cela ne devrait pas être nécessaire.

Je développe ce projet avec C# (3.5) et SQL Server 2008.

Qu'est-ce que l'esprit de la ruche pense?

Répondre

0

Peut-être que je suis sur underthinking, mais ne vous envelopper tout l'ensemble du bloc logique ..

  • valeur lue
  • écriture valeur

dans une transaction de base de données de la appropriate level?

SET TRANSACTION ISOLATION LEVEL 
    { READ UNCOMMITTED 
    | READ COMMITTED 
    | REPEATABLE READ 
    | SNAPSHOT 
    | SERIALIZABLE 
    } 
[ ; ] 
+0

Je ne pense pas n'importe lequel de ces niveaux d'isolement empêchera la lecture à l'étape deux de la première chose (non désirée). Ils permettent tous la lecture de données non modifiées, ou ai-je tort à ce sujet? Les données n'ont pas été modifiées par l'étape 2, donc une lecture devrait être autorisée par tous. – cerhart

+0

Désolé, j'ai manqué ce bit sur la page de Microsoft expliquant: "Aucune autre transaction ne peut modifier les données qui ont été lues par la transaction en cours jusqu'à la fin de la transaction en cours." Cela semblerait répondre à ma question. Merci! – cerhart

Questions connexes