2009-09-04 6 views
7

J'utilise Nhibernate 2.0 dans ASP.NET. Je lance la transaction au début de la page et valide la transaction à la fin. Au cours de la page: - Je reçois un objet - je change la propriété objet - je valide l'objet - si la validation est ok je STOCKER mise à jour sur cet objet - si la validation est erroné, je ne fais pas call to save-update sur cet objet - Je valide toujours la transaction en fin de page.NHibernate commit changements db sans appel explicite pour enregistrer ou mettre à jour

Le problème est que, même lorsque la validation est fausse et que je ne fais aucun appel à enregistrer-mettre à jour sur l'objet, le commit transactin valide le changement dans la base de données.

Je règle le FlushMode sur Never, mais pas sur le changement.

Avez-vous une suggestion? Ce que je me trompe?

+0

Utilisez-vous le framework NHibernate Validation? – mxmissile

Répondre

17

Au cours de la page: - Je reçois un objet

Si vous obtenez un objet d'une session alors vous comprenez mal à jour. La mise à jour consiste à attacher une entité existante à une session. Si vous obtenez une entité d'une session, celle-ci est déjà attachée à cette session, Update n'est donc pas significatif.

SaveOrUpdate vs mise à jour dans ce cas n'a pas d'importance - même chose. NHibernate suit les modifications apportées à l'objet en session. Lorsque vous validez une transaction ou videz une session, elle vérifie les modifications (qui sont possibles), puis les valide dans la base de données. Le but de ceci est que ce n'est pas votre travail de suivre quels objets sont modifiés (sales), c'est NHibernates.

Autre ORM peut exiger que vous suiviez les modifications vous-même et appeliez une sorte de mise à jour explicitement sur tout objet modifié que vous souhaitez conserver, mais NH ne fonctionne pas de cette façon. Donc, pour répondre à votre question, si la validation échoue, vous ne voulez pas valider la transaction. NH est également influencé par le modèle d'unité de travail. Donc, si vous faites le commit dans une partie logique différente du programme de votre logique métier qui valide le travail, cela causera probablement des frictions.

5

Je viens de rencontrer ce même problème. La réponse d'Eyston a été très utile, expliquant que cela n'a pas d'importance si vous appelez ou non ISession.Update (objet) ou SaveOrUpdate (objet), NH suit les changements, et valider la transaction validera les changements.

Il existe plusieurs façons d'effectuer votre validation afin d'empêcher les modifications de se rendre dans la base de données. Effectuez toutes vos validations et sauvegardez (possible) dans une transaction séparée.

using (ITransaction tx = session.BeginTransaction()) 
{ 
    // get your object 
    // do your validation 

    // if you pass validation: 
    tx.Commit(); 

    // if not, roll it back 
    tx.Rollback(); 
} 

J'ai résolu mon problème un peu différemment. Si ma validation échoue, je ne souhaite pas que des mises à jour se produisent pour cet objet en particulier, donc je l'expulserai simplement de la session.

if (!myObj.ValidateForSave()) 
{ 
    session.Evict(myObj); 
} 

Faire de cette façon, vous pouvez coller à votre seule transaction, en commençant au début de la page, et commettre à la fin.Si votre objet a échoué à la validation, il ne sera pas dans la session et aucune modification ne sera conservée dans la base de données.

+4

Si vous avez échoué à une validation, vous devez annuler votre transaction et non la valider. Si vous expulsez un seul objet, les modifications que vous apportez à d'autres objets de la session seront toujours validées et cela va à l'encontre du but d'une transaction étant une opération atomique - cela devrait être "tout ou rien". –

1

La solution qui fonctionne pour moi dans ce cas est:

  1. mis à 'engager la session FlushMode. Supprimez toutes les références à 'Vider' dans le code qui gère les mises à jour en mémoire sur l'objet.

  2. N'ouvrez jamais qu'une seule transaction par session lorsque vous 'sauvegardez', puis supprimez cette session.

Questions connexes