答案 0 :(得分:3)
我遇到了几乎相同的问题。我创建了非null的字段和允许空值的更新字段。看起来你们两个都是非null,所以你可以简单地设置我在下面设置创建字段的更新字段。
我使用了一系列事件监听器。我不能使用PreInsert事件来填充“已创建”字段,因为它在处理后期发生,并且在PreInsert触发之前我得到空检查错误。我使用PreUpdate事件是因为我找不到一种可靠的方法来判断实体是否实际上是脏的,如果我在OnSaveOrUpdate中设置“last_updated”字段,它肯定会使实体变脏并强制每次都发出更新。通过使用PreUpdate,我让NHibernate检查肮脏,我只是在更新触发之前注入我的值。
有关PreUpdate
的详细信息,请参阅此ayende blogpublic 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() };