NHibernate - 没有显式更新的意外更新

时间:2010-02-17 15:28:30

标签: c# java .net nhibernate hibernate

1 个答案:

答案 0 :(得分:3)

我遇到了几乎相同的问题。我创建了非null的字段和允许空值的更新字段。看起来你们两个都是非null,所以你可以简单地设置我在下面设置创建字段的更新字段。

我使用了一系列事件监听器。我不能使用PreInsert事件来填充“已创建”字段,因为它在处理后期发生,并且在PreInsert触发之前我得到空检查错误。我使用PreUpdate事件是因为我找不到一种可靠的方法来判断实体是否实际上是脏的,如果我在OnSaveOrUpdate中设置“last_updated”字段,它肯定会使实体变脏并强制每次都发出更新。通过使用PreUpdate,我让NHibernate检查肮脏,我只是在更新触发之前注入我的值。

有关PreUpdate

的详细信息,请参阅此ayende blog
public class AuditableEventListener : DefaultSaveOrUpdateEventListener, IPreUpdateEventListener
{
    public override void OnSaveOrUpdate(SaveOrUpdateEvent @event)
    {
        Auditable a = @event.Entity as Auditable;
        if (a != null)
        {
            if (this.GetEntityState(@event.Entity, @event.EntityName, @event.Entry, @event.Session) == EntityState.Transient)
            {
                a.create_dt = DateTime.Now;
                a.create_by = @event.Session.Load<Staff>(CurrentStaff.Id);
            }
        }

        base.OnSaveOrUpdate(@event);
    }

    #region IPreUpdateEventListener Members

    public bool OnPreUpdate(PreUpdateEvent @event)
    {
        var audit = @event.Entity as Auditable;
        if (audit == null) return false;

        var now = DateTime.Now;
        var user = @event.Session.Load<Staff>(CurrentStaff.Id);

        //Very important to keep the State and Entity synced together
        Set(@event.Persister, @event.State, "last_update_dt", now);
        Set(@event.Persister, @event.State, "last_update_by", user);

        audit.last_update_dt = now;
        audit.last_update_by = user;

        return false;
    }

    #endregion


    private void Set(IEntityPersister persister, object[] state, string propertyName, object value)
    {
        var index = Array.IndexOf(persister.PropertyNames, propertyName);
        if (index == -1)
            return;
        state[index] = value;
    }

}

然后一定要连接到必需的eventlisteners ......

ISaveOrUpdateEventListener[] saveUpdateListeners = new ISaveOrUpdateEventListener[] { new AuditableEventListener() };
conf.EventListeners.SaveEventListeners = saveUpdateListeners;
conf.EventListeners.SaveOrUpdateEventListeners = saveUpdateListeners;
conf.EventListeners.UpdateEventListeners = saveUpdateListeners;

conf.EventListeners.PreUpdateEventListeners = new IPreUpdateEventListener[] { new AuditableEventListener() };