NHibernate: verrouillage exclusif
Dans NHibernate, je veux récupérer une instance, et de mettre un verrou exclusif sur l'enregistrement que représente l'extrait de l'entité sur la base de données.
Droit maintenant, j'ai ce code:
With.Transaction (session, IsolationLevel.Serializable, delegate
{
ICriteria crit = session.CreateCriteria (typeof (TarificationProfile));
crit.SetLockMode (LockMode.Upgrade);
crit.Add (Expression.Eq ("Id", tarificationProfileId));
TarificationProfile profile = crit.UniqueResult<TarificationProfile> ();
nextNumber = profile.AttestCounter;
profile.AttestCounter++;
session.SaveOrUpdate (profile);
});
Comme vous pouvez le voir, j'ai mis le LockMode pour ce critère de "Mise à niveau".
Ces problèmes d'une instruction SQL pour SQL Server qui utilise le updlock
et rowlock
les indicateurs de verrouillage:
SELECT ... FROM MyTable with (updlock, rowlock)
Cependant, je veux être en mesure d'utiliser un véritable verrou exclusif. C'est, d'empêcher que d'autres peuvent lire ce même dossier, jusqu'à ce que j'ai publié la serrure.
En d'autres termes, je veux être en mesure d'utiliser un xlock
indicateur de verrou, au lieu d'une updlock
.
Je ne sais pas comment (ou même si) je peux le faire .... Peut-être que quelqu'un peut me donner quelques conseils à ce sujet 🙂
Si c'est vraiment nécessaire, je peux utiliser le SQLQuery fonctionnalité de NHibernate, et d'écrire ma propre Requête SQL, mais j'aimerais éviter autant que possible.
Pourquoi ? Parce que c'est nécessaire ... Mon entité contient un compteur qui doit être utilisé, et je doit absolument être sûr que ce compteur est utilisé correctement...
Ne devriez-vous pas de verrouillage lors de la lecture?
Oui, je voudrais verrouiller lors de la lecture, mais c'est ce que je ne peux pas faire, ou au moins, NHibernate ne peut pas le faire. Je veux NHibernate pour émettre un select .. DE table avec des (xlock), mais il ne le fait pas.
Oui, c'est fait. Le RDMBS est SQL Server2005 sp3
OriginalL'auteur Frederik Gheysels | 2009-04-22
Vous devez vous connecter pour publier un commentaire.
Un HQL DML requête permettra d'accomplir votre mise à jour sans avoir besoin d'une serrure.
Cette option est disponible dans NHibernate 2.1, mais n'est pas encore dans la documentation de référence. La Java documentation hibernate est très proche de la NHibernate mise en œuvre.
En supposant que vous utilisez ReadCommitted d'Isolation, vous pouvez en toute sécurité lire votre valeur à l'intérieur de la transaction.
En fonction de vos noms de table et colonne, le SQL généré sera:
Mise à jour de l'exemple pour récupérer la nouvelle valeur
Êtes-vous sûr que vous obtiendrez la bonne AttestCounter ? Je veux dire, il n'y a pas les conditions de la course d'attente pour arriver ici, ou est-il résolu par le niveau d'isolation Serializable ?
Toute conclusion sur ce sujet? J'aimerais savoir si cette approche fonctionne ou pas. (si il a fait un travail, vous devez accepter la réponse)
Frederik: vous n'avez même pas besoin serializable - readcommitted est fine parce que vous écrivez avant de lire à l'intérieur de la tx.
OriginalL'auteur Lachlan Roche
Je doute qu'il peut être fait à partir de NHibernate. Personnellement, je voudrais utiliser une procédure stockée pour faire ce que vous essayez d'accomplir.
Mise à jour: compte tenu de la poursuite downvotes, je vais développer sur ce. Frederick se demande comment utiliser les indicateurs de verrouillage, qui sont de la syntaxe et de la mise en œuvre des détails spécifiques de son sous-jacent moteur de base de données, à partir de sa couche ORM. C'est le mauvais niveau de tenter d'effectuer une telle opération, même si elle était possible (n'est pas), la probabilité qu'il ne serait jamais travailler de manière cohérente à travers tous les NHibernate-pris en charge des bases de données est extrêmement faible.
Il est grand Frédéric éventuelle solution n'a pas besoin de préemption des verrous exclusifs (qui tue les performances et sont généralement une mauvaise idée, sauf si vous savez ce que vous faites), mais ma réponse est valable. Toute personne qui bute sur cette question et veut faire exclusif-lock-on lire à partir de NHibernate - tout d'abord: ne le faites pas, d'autre part: si vous devez utiliser une procédure stockée ou une SQLQuery.
OriginalL'auteur Sam
Si tout ce que vous lisez sont effectués avec un IsolationLevel de Serializable et tous les écriture sont également fait avec un IsolationLevel de Serializable je ne vois pas pourquoi vous devez faire tout de verrouillage de la base de données des lignes de votre auto.
Donc la sérialisation permet de conserver les données en sécurité, maintenant, nous avons encore le problème de la possible mort de serrures....
Si les blocages ne sont pas communs, vient de mettre la [start transaction, lire, mettre à jour, sauvegarder] dans une nouvelle tentative de la boucle lorsque vous obtenez un blocage peut être assez bon.
Sinon un simple “select for update” déclaration généré directement (par exemple, pas avec nhibernate) pourrait être utilisé pour arrêter une autre opération de lecture de la ligne avant qu'elle soit changée.
Cependant, je continue à penser que si le taux de mise à jour est assez rapide à obtenir beaucoup de blocages d'un ORM peut-être pas le bon outil pour la mise à jour, ou le schéma de base de données peuvent avoir besoin de refonte afin d'éviter la valeur qui doit être lu/écrit (e.g de calcul lors de la lecture de données)
merci je l'ai mise à jour de ma réponse à inclure les blocages
OriginalL'auteur Ian Ringrose
Vous pouvez utiliser le niveau d'isolation "repeatable read" si vous voulez vous assurer que les valeurs que vous lisez à partir de la base de données ne changent pas au cours de la transaction. Mais vous devez le faire dans toutes les transactions essentielles. Ou vous l'enfermez dans la lecture critique d'une transaction avec une mise à niveau de verrouillage.
Si l'entité ne peut pas changer au cours de cette opération. Autres opérations peut lire la valeur, et ils peuvent voir vos modifications lors de leur transaction. S'ils n'aiment pas cela, ils doivent faire leur propre cadenas. Ou d'utiliser des "repeatable read".
OriginalL'auteur Stefan Steinegger