I use Nhibernate 2.0 in ASP.NET. I start the transaction at the begging of the page and commit the transaction at the end. During the page: - I get an object - I change the
During the page: - I get an object
If you get an object from a session then you are misunderstanding Update. Update is for attaching an existing entity to a session. If you get an entity from a session it is already attached to that session so Update is meaningless.
SaveOrUpdate vs. Update in this case doesn't matter -- same thing.
NHibernate tracks changes to the object in session. When you commit a transaction or flush a session it is going to check for any changes (which there are) and then commit those to the database. The whole point of this is that it isn't your job to track which objects are changed (dirty), it is NHibernates.
Other ORM may require that you track the changes yourself and call some kind of Update explicitly on any object changed that you want to persist, but NH doesn't work that way.
So to answer your question, if validation fails you don't want to commit the transaction.
NH is also opinionated towards the Unit of Work pattern. So if you do the commit in a different logical part of the program from your business logic that is validating work, it probably will cause friction.
The solution that works for me in this case is:
Set the Session FlushMode to 'Commit'.
Remove all references to 'Flush' in the code handling the in-memory updates on the object.
Only ever open 1 transaction per session when 'saving' and then discard that session.
I just ran into this same problem. Eyston's answer was very helpful, explaining that it doesn't matter whether or not you call ISession.Update(object) or SaveOrUpdate(object), NH tracks the changes, and committing the transaction will commit the changes.
There are a few ways you can accomplish your validation then, to prevent changes going to the database. Do all of your validation and (possible) saving in a separate transaction.
using (ITransaction tx = session.BeginTransaction())
{
// get your object
// do your validation
// if you pass validation:
tx.Commit();
// if not, roll it back
tx.Rollback();
}
I have solved my problem a bit differently. If my validation fails, I don't want any updates to occur for that particular object, so I simply evict it from the session.
if (!myObj.ValidateForSave())
{
session.Evict(myObj);
}
Doing it that way, you can stick to your single transaction, starting it at the beginning of the page, and committing it at the end. If your object failed validation, it won't be in the session, and no changes will be persisted to the database.