2011-06-29 16 views
1

如何從NHibernate中的多個集合和列表中檢測更改(添加和刪除)?我使用攔截器來檢測對象模型(用於審計和更多)的更改,這對於對象內部的更改(使用OnSave/OnFlushDirty)非常有用,但對於集合不起作用。如何檢測NHibernate中的集合更改

當集合更改時,OnCollectionUpdate方法被調用,但它只接收持有集合的對象的鍵和集合的最新項目。

我需要的是:

  1. 持有集合的對象(或至少類型+關鍵,關鍵是在我的系統一類中只有唯一的)我只有現在的關鍵。

  2. 集合(我有多個集合類)

  3. 添加物品的清單和已刪除項目(或者,當前交易之前和之後收集的內容)的列表的屬性名稱。

有什麼辦法可以得到這些信息嗎?

回答

0

也許有點棘手,但是如何創建自定義代理?

+0

我真的不知道這對我有何幫助。我沒有問題檢測正常對象屬性中的更改,只是在集合中 - 並且集合的添加和刪除方法未在代理上調用(另外,這對於未延遲加載的對象不起作用) – Nir

+0

@Nir so你可以攔截修改修改... –

+0

如果我們使用博客數據模型爲例,當有人調用post.Comments。添加評論屬性getter在代理上被調用,並且可以被它捕獲 - 但是這並不告訴我Add是被調用的(它可能是一個來自foreach循環的GetEnumerator,對於我所知道的),它不會告訴我增加了什麼。 – Nir

1

我目前正在自己​​的工作。我還沒有想出你自己的第三次還的問題(我試圖找出雖然),但這應該幫助你的方式,以#1和#2:

public static void SomeMethod(this ISession session, object entity) 
{    
    //this will give you the information about your entity 
    String className = NHibernateProxyHelper.GuessClass(entity).FullName; 
    ISessionImplementor sessionImpl = session.GetSessionImplementation(); 
    IEntityPersister persister = sessionImpl.Factory.GetEntityPersister(className); 

    //at this point you can use the persister object to retrieve the info you need: 

    //this gives you all properties and their values 
    Object[] currentState = persister.GetPropertyValues(entity, sessionImpl.EntityMode); 

    //this will return the types: 
    IType[] typeArray = persister.PropertyTypes; 

    //each IType object has a IsCollectionType bool which tells you if it is a collection: 
    bool isCollection = IType[0].IsCollectionType; 
} 
0

這是 NHibernate的代碼(這是Hibernate的Java代碼),但谷歌搜索NHibernate的API使它看起來像類似的代碼可以讓你開始爲NHibernate的,以及(有一個PersistentMap類具有Owner財產和CollectionSnapshot屬性):

public void onCollectionUpdate(Object collection, Serializable id) { 
    System.out.println("****onCollectionUpdate"); 

    if(collection instanceof PersistentMap) { 
     PersistentMap newValues = (PersistentMap) collection; 
     Object owner = newValues != null ? newValues.getOwner() : null; 
     Set<?> oldValues = newValues != null 
      ? ((Map<?, ?>) newValues.getStoredSnapshot()).keySet() 
      : null; 

     System.out.println("owner: " + (owner != null ? owner.toString() : "(null)")); 
     System.out.println("oldValues: " + (oldValues != null ? oldValues.toString() : "(null)")); 
     System.out.println("newValues: " + (newValues != null ? newValues.toString() : "(null)")); 
    } else if (collection instanceof PersistentSet) { 
     PersistentSet newValues = (PersistentSet) collection; 
     Object owner = newValues != null ? newValues.getOwner() : null; 
     Set<?> oldValues = newValues != null 
      ? ((Map<?, ?>) newValues.getStoredSnapshot()).keySet() 
      : null; 

     System.out.println("owner: " + (owner != null ? owner.toString() : "(null)")); 
     System.out.println("oldValues: " + (oldValues != null ? oldValues.toString() : "(null)")); 
     System.out.println("newValues: " + (newValues != null ? newValues.toString() : "(null)")); 
    } 
} 

請注意,我知道這不是C#或NHibernate代碼。請評論,如果這是完全無用的NHibernate(如果API不完全相似,即使我的谷歌搜索說它是相似的),我會刪除帖子。

我沉浸在Java的土地的權利,或者我會嘗試這個爲你:)

1

如果你沒有重載非標準NHibernate的集合(列表,設置,地圖),你總是可以得到初始收藏內容(在任何變化之前保存在基地的內容)。列表示例:

PersistentList c = myCollection as PersistentList; 
if ((c == null)||(!c.IsDirty)) { 
     return; 
} 
IEnumerable storedCollection = c.StoredSnapshot as IEnumerable; 
if ((storedCollection == null)) { 
     return; //looks like a error 
} 
foreach(var element in storedCollection) { 
    //do something with old items 
} 
foreach(var element in storedCollection) { 
    //do something with new items 
} 

當然,您可以確定哪些元素已被添加,刪除或保持不變。

+0

爲什麼不能將快照內容與實際持久性收藏內容進行比較? –