简体   繁体   English

nhibernate 审计更新事件

[英]nhibernate auditing with events on update

The following code works on insert but on update modifier is never set, any ideas why?以下代码适用于插入,但从未设置更新modifier ,有什么想法吗?

The code for pre-update is being run and correctly sets the state and entity values to the desired value.预更新代码正在运行并将 state 和实体值正确设置为所需值。 However when viewing the generated sql nhibernate does not include the field in the update query.但是查看生成的 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 */ }
    }

}

Edit 1: This answer has been improved 编辑1:这个答案有所改进
Edit 2: It appears the the real cuase of the problem is dynamic-update set to true as found here however this solution still works for me. 编辑2:看来在这个问题的真正cuase是动态更新设置为true 这里找到不过这个解决方案仍然为我工作。

The changes get saved when you update them in the OnFlushDirty function which is called earlier. 在先前调用的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;
}

For us it was because NHibernate was joining tables together with the same column names;对我们来说,这是因为 NHibernate 将具有相同列名的表连接在一起; so we'd update the first instance of that column name, but not the subsequent ones.所以我们会更新该列名的第一个实例,但不会更新后续的实例。 We did this:我们这样做了:

    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);
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM