断开会话时,仅更新NHibernate中已更改的属性的最佳方法是什么?

问题描述:

我正在研究使用NHibernate的项目. 我没有打开会议.当我需要获取或保存对象时,我打开会话,执行所需的操作,然后关闭会话.因此,一直以来,我一直在处理与会话分离的对象.

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.

例如,当我需要从数据库中获取对象时,我打开会话,然后调用session.Get()并关闭会话.然后,我更新分离对象的某些属性.当我需要将更改保存到数据库时,我调用打开会话的方法,调用session.Update(myObject)并关闭会话.

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.

但是当我这样做时,NHibernate会生成sql来更新我已映射的所有字段,即使它们没有更改.我的建议是,当从会话中分离对象时,NHibernate无法跟踪所做的更改. 当您只想更新从会话分离的对象已更改的属性时,使用哪种方法?如何跟踪分离对象的更改?

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?

谢谢

问题是:为什么要这样做?我认为,如果仅更新已更改的列,那并不是什么优化.

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:

  • 在映射中使用select-before-update="true"dynamic-update="true".这使NH可以在更新之前执行查询,并且仅在更改后才更新,并且仅更改了列.我不确定是为每个更新选择它,还是只有它不在会话中才选择.
  • 使用Merge代替更新.这实际上是一样的:仅当数据库尚未在会话中时,才从数据库中选择该实体.也使用dynamic-update="true".还有一个折衷方案:如果会话中已经有一个实例,则Merge返回附加的实例.因此,您应该始终丢弃传入的实例,并使用来自Merge的实例.
  • 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.