2010-07-02 66 views
5

下面的代碼工作插入,但更新modifier從未設置,任何想法爲什麼?nhibernate審計與更新事件

正在運行預更新的代碼,並正確地將狀態和實體值設置爲所需的值。但是,查看生成的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 */ } 
    } 

} 
+0

這段代碼對我來說看起來不錯,儘管Set方法並不常見。如果你在OnPreUpdate上放置一個斷點,當你持久化一個更新的對象時它會被調用嗎? – 2010-07-02 13:07:17

+0

是的,我認爲這個問題與那些不被nhibernate視爲髒的財產有關。 – 2010-07-02 23:37:48

回答

3

編輯1:這個答案得到了提高
編輯2:這顯示了問題的真正cuase是動態更新設置爲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; 
} 
+0

你的鏈接「答案」只是鏈接回到同一頁....... – 2011-04-14 14:02:27

+0

@Max Schilling對不起,這個答案是否更好? – 2011-08-27 01:18:21