2008-09-23 8 views
1

J'ai une application ASP.NET qui utilise NHibernate pour mettre à jour de manière transactionnelle quelques tables lors d'une action de l'utilisateur. Il existe une plage de dates dans laquelle une seule entrée dans une table "Réservation" peut être effectuée de telle sorte que des dates exclusives sont spécifiées.Transaction NHibernate et condition de concurrence

Mon problème est de savoir comment éviter une situation de course dans laquelle deux actions de l'utilisateur se produisent presque simultanément et provoquent des entrées multiples dans "Réservation" pour> 1 date. Je ne peux pas vérifier juste avant d'appeler .Commit() parce que je pense que cela restera toujours avec une condition de course?

Tout ce que je peux voir est de faire un contrôle après le commit et rouler le changement de retour manuellement, mais cela me laisse avec un très mauvais goût dans ma bouche! :)

booking_ref (INT) PRIMARY_KEY AUTOINCREMENT

booking_start (DATETIME)

booking_end (DATETIME)

Répondre

5
  • faire le niveau d'isolation de votre transaction SERIALIZABLE (session.BeginTransaction(IsolationLevel.Serializable) et vérifier et insérer dans la même transaction. Vous ne devez généralement pas définir isolationlevel sur sérialisable, juste dans des situations comme celle-ci.

ou

  • verrouiller la table avant de vérifier et éventuellement insérer. Vous pouvez le faire en lançant une requête SQL via nhibernate:

    session.CreateSQLQuery ("SELECT null comme dummy FROM Réservation WITH (tablockx, holdlock)"). AddScalar ("dummy", NHibernateUtil.Int32); Cela verrouille uniquement cette table pour les sélections/insertions pendant la durée de cette transaction.

L'espoir a aidé

+0

Bien sûr - je ne peux pas croire que j'ai réussi à rater complètement en utilisant des serrures de table, avait un blanc mental! Merci beaucoup. –

-1

Votre base de données devrait gérer l'intégrité des données.

Vous pourriez rendre votre colonne "date" unique. Par conséquent, si 2 threads tentent d'obtenir la même date. L'un va lancer une violation de clé unique et l'autre va réussir.

0

Les solutions ci-dessus peuvent être utilisées en option. Si j'ai envoyé une requête de 100 en utilisant "Parallel.For" alors que le niveau de la transaction est sérialisable, yess il n'y a pas d'ID reqeust dupliqué mais la transaction 25 échoue. Ce n'est pas acceptable pour mon client. Nous avons donc résolu le problème en stockant uniquement l'identifiant de la requête et en ajoutant un index unique sur l'autre table en tant que temp.

Questions connexes