NHibernate - flagging specific properties as 'dirty'

◇◆丶佛笑我妖孽 提交于 2019-12-02 03:49:18

Dynamic-update is what you're looking for. In your mapping file (hbm.xml):

<class name="Foo" dynamic-update="true">
   <!-- remainder of your class map -->

Be aware of the potential problems that this may cause. Let's say you have some domain logic that says either FirstName or Nickname must not be null. (Completely making this up.) Two people update Jon "Jonboy" Jonson at the same time. One removes his FirstName. Because dynamic-update is true, the update statement just nulls out Jon and the record is now "Jonboy" Jonson. The other simultaneous update removes his Nickname. The intent is Jon Jonboy. But only the null-out of the Nickname gets sent to the database. You now have a record with no FirstName or Nickname. If dynamic-update had been false, the second update would have set it to Jon Jonboy. Maybe this isn't an issue in your situation, but setting dynamic-update="true" has consequences and you should think through the implications.

UPDATE: Thanks for the code. That helped. The basic problem is NHibernate not having enough information. When you say session.Update(p), NHibernate has to associated a disconnected entity with the current session. It has a non-default PK. So NHibernate knows that it's an update and not an insert. When you say session.Update(p), NHibernate sees the whole entity as dirty and sends it to the database. (If you use session.Merge(obj), NHibernate selects the entity from the database and merges obj with it.) This is not what you really mean. You want to associate your object with the current session, but mark it as clean. The API is somewhat non-intuitive. You use session.Lock(obj, LockMode.None) as below.

using(var session = sessionFactory.OpenSession())
using(var tx = session.BeginTransaction()) {
    var p = new Person {PersonId = 1};
    session.Lock(p, LockMode.None); // <-- This is the secret sauce!
    p.Firstname = "Bob";
    // No need to call session.Update(p) since p is already associated with the session.
    tx.Commit();
}

(N.B. dynamic-update="true" is specified in my mapping.)

This results in the following SQL:

UPDATE Person
SET    Firstname = 'Bob' /* @p0_0 */
WHERE  PersonId = 1 /* @p1_0 */
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!