tags:

views:

1154

answers:

2

I am working on the project which uses NHibernate. I don't keep session opened. When i need to get or save object, i open the session, do what i need and then close the session. So all the time i'm working with objects detached from session.

For example, when i need to get object from the database, i open the session, then call session.Get() and close the session. Then i update some properties of detached object. When i need to save changes to the database i call method that opens session, calls session.Update(myObject) and closes the session.

But when i do so, NHibernate generates sql that updates all the fields I have mapped, even though they have not changed. My suggestion is when objects is detached from session, NHibernate couldn't track the changes has been made. What approach do you use when you want to update only properties that has been changed for object detached from session? How do you track the changes for detached objects?

Thanks

+1  A: 

Use dynamic-update="true" in the mapping.
Additionally to update detached object use this:

Session.SaveOrUpdateCopy(myObject)
Dmytrii Nagirniak
I'd like to accept this as the answer, just want to ask you one more thing: what is the difference between SaveOrUpdateCopy and Merge? Could i use Merge for detached objects or SaveOrUpdateCopy is a better approach?
Sergey
dynamic-update only works on attached entities. How should NH determine which properties have changed if it doesn't have the old state in the session?
Stefan Steinegger
I don't why, but when i set dynamic-update attribute and say SaveOrUpdateCopy or Merge it saves only changed columns for my object. When i removed the dynamic-update attribute, NHibernate again saves all the properties even if i changed only one! But how it works is a question...
Sergey
With Merge it works, with SaveOrUpdateCopy I don't know. Your entity is probably already attached?
Stefan Steinegger
Sorry, I have to correct myself. It works as you say, with dynamic-update and SaveOrUpdateCopy (I didn't recognize the "Copy"). But SaveOrUpdateCopy is deprecated in hibernate (the java one) and replaced by merge. So I would use Merge - If I had to do this anyway - see my answer.
Stefan Steinegger
+3  A: 

The question is: why do you want to do this? I think it is not much of an optimization if you only update columns that have changed.

Have you got triggers in the database?

If so, you can do the following:

  • use select-before-update="true" and dynamic-update="true" in the mapping. This makes NH to perform a query before the update and only updates if it changed, and only the columns that have changed. I'm not sure if it selects for every update, or only if it is not in the session.
  • use Merge instead of update. This does actually the same: it selects the entity from the database, only if it is not already in the session. Also use dynamic-update="true". There is also a trade-off: Merge returns the attached instance if there is already one in the session. So you should always throw away the instance you passed in and work with the instance you go from Merge.

Actually I wouldn't care about the updated columns. Its most probably faster to update them blindly instead of performing a preceding query.

Stefan Steinegger
I don't have any triggers in the database. Well, i want to do this just because i used to update only properties has been changed. Do you mean that update objects blindly could be faster and Merge needs some additional resources?
Sergey
By the way, why should i use select-before-update="true" if it is work without it?
Sergey
Merge needs an additional query, this is an additional db round-trip and has its overhead. I think that select-before-update is just to avoid Merge. Merge has its impact to the business logic.
Stefan Steinegger