1

J'ai une entité mappée dans NHibernate avec un contrôle de concurrence optimiste utilisant une colonne d'horodatage SQL comme numéro de version. La cartographie est comme ce qui suit:NHibernate ne lançant pas StaleObjectStateException lorsque <Version> utilisé et les données ont changé dans la base de données

<class name="Entity" optimistic-lock="version" discriminator-value="0"> 
    <id name="id"> 
     <generator class="native" /> 
    </id> 
    <version name="Version" column="Version" generated="always" unsaved-value="null" type="System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 
    ... 
    <subclass name="ChildEntity" discriminator-value="1" /> 
</class> 

Je teste ce qui se passe lorsque les données d'une ligne dans la base de données change entre le get et la mise à jour de l'enregistrement. Pour ce faire, je lance une instruction de mise à jour directement sur l'un des enregistrements de la table qui sont en cours de mise à jour par NHibernate. Cette mise à jour directe modifie le numéro de version de l'enregistrement dans la table.

Comme prévu, la mise à jour gérée par NHibernate ne se produit pas sur la ligne spécifique (c'est bien). Cependant, aucune exception n'est levée pendant la validation. Je m'attendais à une StaleObjectStateException à se produire lorsque la transaction a été validée afin que je puisse annuler la transaction et informer l'utilisateur. N'est-ce pas le comportement attendu? Est-ce que je manque quelque chose?

mon code pour valider la transaction ressemble à quelque chose comme ceci:

_session.BeginTransaction(); 
... 
// load objects in session 
IList<ChildEntity> toChange = _session.Find('some condition'); 
foreach (var itemToChange in toChange) 
{ 
    itemToChange.Status = Status.Updated; 
} 
... 
_session.Transaction.Commit(); 

Les éléments appartiennent à la même session et tous les travaux sont terminés dans une seule transaction. ChildEntity est une sous-classe de la classe de base Entity, dont le jeu optimistic-lock est défini sur version.

Répondre

0

Il semble que mon test était inexact. Dans le test, je faisais le get après que l'autre transaction a mis à jour l'enregistrement. Cette autre mise à jour a rendu la ligne inéligible pour la mise à jour, donc aucune mise à jour n'a été tentée. Lorsque j'ai changé le test pour que la mise à jour concurrente APRÈS le Get, l'exception StaleObjectStateException a été lancée comme prévu.

Désolé pour la confusion.

5

Comment modifiez-vous les données? L'exception StaleObjectException est levée uniquement lorsque NHibernate tente de mettre à jour la ligne et que le numéro de version n'est plus le même. Les autres colonnes ne sont pas pertinentes. Est-il possible que lors de vos tests, vous ne mettiez pas à jour le numéro de version?

La prémisse est la suivante:

A. L'utilisateur Un objet get & B base de données avec la version = 1

SQL: SELECT [object] FROM [TABLE] where id = [id] and Version = 1

B. utilisateur Un objet Mises à jour qui modifie la version 2

SQL: UPDATE [TABLE] SET [object] (& Set Version = 2) where id = [id] and Version = 1 retourne 1 ligne mise à jour

C. tentatives utilisateur B pour mettre à jour l'objet mais obtient StaleObjectException en tant qu'objet de mise à jour avec version = 1 (la version qu'il a obtenue l'étape 1) met à jour 0 enregistrements dans la base de données.

SQL: UPDATE [TABLE] SET [object] where id = [id] and Version = 1 renvoie 0 lignes mises à jour et StaleObjectException levées.

Questions connexes