tags:

views:

21

answers:

1

How do i roll back changes to an attached object in nhibernate? We have a validation before update/save (example simplified)..

var setting = Get("key")
setting.Value = "helo" //for whatever reason, this particular 
                       //setting cannot have its value saved to the database
...
Verify(setting);       //throws
base.Update(setting);

but since the object is attached, any changes already happened in the session, even if the validation throws, and never reaches Update. What is the proper way to handle this?

A: 

This is most probably because the surrounding transaction commits, even an exception is thrown. Or you catches the exception later on and hide the error from the surrounding transaction. The update could be performed by NH whenever it flushes the session, for instance before executing queries. Committing always synchronizes the memory state to the database.

Update is only needed for instances which are not in the session yet (but in the database). Everything in the session is synchronized to the database, any any point in time, at the latest when committing.

One of the advantages of NH is what is called "persistence ignorance". This means, after instances are loaded to memory, you logic doesn't care about persistency anymore. You're using your classes like any other, at the end everything will be persisted (or rolled back) in an atomic way.

So what does this all mean for your code?

  • Write your code as if there weren't NHibernate or persistency. This will also enhance maintainability and testability.
  • What you are doing in memory is definitive. You don't have a second "store" step. Don't do things you don't want to do.
  • Your memory needs to be as consistent as the database. Your logic is always based on memory state (eg. calculations). Inconsistent memory will break consistency of the application. So you shouldn't commit when you have data in memory you don't want in the database.
  • Commit is all or nothing. Either you are happy with your changes or you roll back everything.
  • Exception handling is tricky. It's not always easy to decide if you can carry on with the transaction.
  • Changing the state of the entity is responsibility of your business logic. NHibernate will not "reset" a single instance. (There is a Refresh, but it will not work here and you shouldn't use it anyway). So if you want to reset a value, you need to write business logic which resets the value.
Stefan Steinegger
So basically i should either detach the objects when they are out of my control (worse), or validate whenever the value of the setting is set (better), to be sure that they are valid?
hhravn
You should rollback the whole transaction if data is not valid. If you only want to change values when they are valid, you need to validate them before changing the entity. If you want to fix single values after setting them on the entity, when fix single values by an additional logic. Don't depend on (not) calling Update and don't depend on evict (detach). Don't depend on the fact that the database knows (probably) the original value. Your business logic is based on objects, it only knows one value, the actual one, after changing it, the original value is lost.
Stefan Steinegger