Question

Le problème que je pose est la suivante:

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

ID int
Value int

I 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. L'utilisateur Une méthode appelle et obtient la valeur (actuellement 5)
  2. méthode appelle l'utilisateur B et obtient la valeur (actuellement 5)
  3. L'utilisateur A augmente la valeur de 5 (maintenant 10)
  4. L'utilisateur B augmente la valeur de 5 (maintenant 10)
  5. L'utilisateur Une valeur enregistre (10)
  6. B valeur permet d'économiser de l'utilisateur (10)

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

Ce que je veux à la force est la suivante:

  1. L'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. L'utilisateur A augmente la valeur (maintenant 10)
  4. L'utilisateur B attend toujours
  5. L'utilisateur A enregistre la valeur (enregistrement a une valeur de 10)
  6. L'utilisateur B peut maintenant lire la valeur (10)
  7. L'utilisateur B augmente la valeur (15)
  8. L'utilisateur B enregistre la valeur

Maintenant, le disque a une valeur de 15, ce qui est le résultat que je cherche.

Je l'ai résolu ce problème dans le passé en utilisant une classe statique et mettre un verrou sur un objet statique créé au sein du constructeur de cette classe, canalisant ainsi tout le travail par une méthode statique, ce qui oblige les autres appels à attendre en ligne . Je crains cependant que ce n'est pas évolutive.

Je pense aussi que le niveau d'isolement le plus élevé (sérialisable) pour une transaction ne fera pas l'affaire soit parce qu'elle permettra à la lecture à l'étape 2 de l'exemple ci-dessus indésirable.

Je suppose une autre solution serait de créer ma propre table de verrouillage et d'enregistrer les verrous là-bas, mais cela semble que cela ne devrait pas être neccessary.

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

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

Était-ce utile?

La solution

Peut-être que je suis sur underthinking, mais ne serait pas vous conclure tout le bloc logique ..

  • valeur lue
  • valeur d'écriture

dans une transaction de base de données de la niveau approprié?

SET TRANSACTION ISOLATION LEVEL
    { READ UNCOMMITTED
    | READ COMMITTED
    | REPEATABLE READ
    | SNAPSHOT
    | SERIALIZABLE
    }
[ ; ]
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top