2009-07-20 106 views
11

我使用DDD和NHibernate來堅持我的域對象。在我的數據庫中,與實體相關的每個表都有四個用於審計跟蹤的額外列(CreatedBy,UpdatedBy,CreatedDate,UpdatedDate)。我正在使用僅允許保存聚合根的存儲庫模式。當NHibernate試圖保存聚合根上的實體時,我得到一個SQL DateTime錯誤,因爲這些實體沒有設置它們的審計屬性。 NHibernate中有一種方法可以在保存之前設置對象的屬性嗎?NHibernate自動設置屬性保存

這是一個小例子。我有一個Order對象,它是聚合根。我也有訂單子項目的OrderNote對象。當我將OrderNote添加到Order並保存Order時,會拋出一個異常,因爲將CreatedDate/UpdatedDate設置爲DateTime.MinValue會導致SQL DateTime溢出。由於這些審計列是持久性的一部分,並且與問題域無關,因此我不希望訂單聚合根在添加註釋時設置這些屬性。審計列/屬性只應由持久性框架而不是域來知曉。我希望能夠告訴NHibernate在保存或更新時設置這些屬性。有沒有辦法做到這一點?

回答

11

攔截器可以做到這一點:

http://www.nhforge.org/doc/nh/en/index.html#manipulatingdata-interceptors(9.10,鏈接並不總是有效)。

剪切/膏從文檔:

public class AuditInterceptor : IInterceptor 
{ 
    ... 

    public boolean OnSave(object entity, 
          object id, 
          object[] state, 
          string[] propertyNames, 
          IType[] types) 
    { 
     if (entity is IAuditable) 
     { 
      for (int i=0; i<propertyNames.Length; i++) 
      { 
       if ("CreateTimestamp" == propertyNames[i]) 
       { 
        state[i] = DateTime.Now; 
        return true; 
       } 
      } 
     } 
     return false; 
    } 

} 

OnFlushDirty()可用於UpdatedDate。

您將希望每個擁有CreatedDate/UpdatedDate的實體都實現一個接口,以便攔截器可以檢查它是否應該起作用(在提供的示例中,它是IAuditable)。


編輯

只注意到第11章:攔截器和事件。您可以從EmptyInterceptor繼承,如果您只需要重寫某些方法,就可以使事情變得更輕鬆。

我從來沒有使用過活動。

+0

很好。這正是我要找的。我是NHibernate的新手,並沒有意識到這個功能。我確實有一個用受保護屬性實現的IAuditable接口,因此域無法看到它們。 – awilinsk 2009-07-20 14:54:35

1

你也可以看看NHibernate的版本控制系統,它可以幫助你的情況;)