tags:

views:

354

answers:

2

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 object property - I validate the object - if validation is ok I call save-update on that object - if validation is wrong i don't make any call to save-update on that object - I always commit the transaction at the end of page.

The problem is that also when the validation is wrong and i dont make any call to save-update on the object the commit transactin commit the change in the DB.

I set the FlushMode to Never but nothig change.

Have suggestion? What I mistake?

+7  A: 

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.

eyston
+3  A: 

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.

Samuel Meacham
If you have a failed validation, you should roll back your transaction, not commit it. If you evict a single object, changes you make to other objects in the session will still be committed and this goes against the grain of a transaction being an atomic operation - it should be "all or nothing".
Mike Scott