使用更新事件进行休眠审计
Posted
技术标签:
【中文标题】使用更新事件进行休眠审计【英文标题】:nhibernate auditing with events on update 【发布时间】:2011-03-11 00:42:28 【问题描述】:以下代码在插入时有效,但在更新时 modifier
从未设置,有什么想法吗?
预更新代码正在运行,并将状态和实体值正确设置为所需值。但是在查看生成的sql时,nhibernate不包括更新查询中的字段。
/// <summary> Updates auditable objects </summary>
public class AuditEventListener : IPreInsertEventListener, IPreUpdateEventListener
private ISecurityManager securityManager;
public bool OnPreInsert( PreInsertEvent args )
var auditable = args.Entity as IAuditable;
if (auditable != null)
Set( x => auditable.Creator, args.Persister, auditable, args.State, SecurityManager.Identity );
Set( x => auditable.DateAdded, args.Persister, auditable, args.State, Clock.Now );
return false;
public bool OnPreUpdate( PreUpdateEvent args )
var auditable = args.Entity as IAuditable;
if (auditable != null)
Set( x => auditable.Modifier, args.Persister, auditable, args.State, SecurityManager.Identity );
//Set( x => auditable.DateModified, args.Persister, auditable, args.State, Clock.Now );
return false;
/// <summary> Type safe method to update sate and entity </summary>
private void Set<T, U>( Expression<Func<U, T>> expression, IEntityPersister persister, U instance, object[] state, T value )
var member = expression.Body as MemberExpression;
if (member != null)
var index = Array.IndexOf( persister.PropertyNames, member.Member.Name );
if (index == -1)
return;
state[index] = value;
var property = (member.Member as PropertyInfo);
if (property != null)
property.SetValue( instance, value, null );
ISecurityManager SecurityManager
get /* From IoC */
【问题讨论】:
这段代码对我来说看起来不错,尽管 Set 方法不常见。如果你在 OnPreUpdate 上设置断点,当你持久化一个更新的对象时它会被调用吗? 是的,我认为问题与该属性不被 nhibernate 视为脏有关。 【参考方案1】:编辑 1:此答案已改进 编辑 2:看来问题的真正原因是 dynamic-update 设置为 true 为 found here 但是这个解决方案仍然适用于我。
当您在之前调用的 OnFlushDirty 函数中更新它们时,更改会被保存。
public override bool OnFlushDirty( object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types )
bool result = false;
if (entity is IAuditable)
var auditable = (IAuditable)entity;
Set( x => auditable.Modifier, propertyNames, auditable, currentState, SecurityManager.Identity );
//Set( x => auditable.DateModified, args.Persister, auditable, args.State, TwentyClock.Now );
result = true;
return result;
【讨论】:
@Max Schilling 抱歉,这个答案更好吗?【参考方案2】:对我们来说,这是因为 NHibernate 将具有相同列名的表连接在一起;所以我们会更新该列名的第一个实例,而不是后续的。我们这样做了:
protected void Set(IEntityPersister persister, object[] state, string propertyName, object value)
var index = Array.IndexOf(persister.PropertyNames, propertyName);
while (index > -1)
state[index] = value;
index = Array.IndexOf(persister.PropertyNames, propertyName, index + 1);
【讨论】:
以上是关于使用更新事件进行休眠审计的主要内容,如果未能解决你的问题,请参考以下文章