如何检测NHibernate中的集合更改

如何检测NHibernate中的集合更改,nhibernate,collections,Nhibernate,Collections,如何检测NHibernate中多对多集合和列表的更改(添加和删除) 我正在使用拦截器来检测对象模型中的更改(用于审计等),这对于对象内的更改(使用OnSave/OnFlushDirty)非常有效,但对于集合则不适用 当集合更改时,将调用OnCollectionUpdate方法,但它只接收保存集合的对象的键和集合的最新项 我需要的是: 持有集合的对象(或者至少是type+key,该键仅在我的系统中的类中是唯一的)我现在只有该键 集合的属性名称(我有多个集合的类) 添加项列表和删除项列表(或者,当前

如何检测NHibernate中多对多集合和列表的更改(添加和删除)

我正在使用拦截器来检测对象模型中的更改(用于审计等),这对于对象内的更改(使用OnSave/OnFlushDirty)非常有效,但对于集合则不适用

当集合更改时,将调用OnCollectionUpdate方法,但它只接收保存集合的对象的键和集合的最新项

我需要的是:

  • 持有集合的对象(或者至少是type+key,该键仅在我的系统中的类中是唯一的)我现在只有该键

  • 集合的属性名称(我有多个集合的类)

  • 添加项列表和删除项列表(或者,当前事务前后的集合内容)


  • 有什么方法可以获得这些信息吗?

    可能有点棘手,但是创建一个自定义代理怎么样?

    我目前正在自己处理这个问题。我自己还没有弄明白你的第三个问题(不过我正在努力找出答案),但这应该能帮助你解决第1和第2个问题:

    这不是NHibernate代码(它是Hibernate Java代码),但通过谷歌搜索NHibernate API,看起来类似的代码也可以让您开始使用NHibernate(有一个
    PersistentMap
    类,它有一个
    Owner
    属性和一个
    CollectionSnapshot
    属性):

    public void onCollectionUpdate(对象集合,可序列化id){
    System.out.println(“**onCollectionUpdate”);
    if(PersistentMap的集合实例){
    PersistentMap newValues=(PersistentMap)集合;
    对象所有者=newValues!=null?newValues.getOwner():null;
    设置oldValues=newValues!=null
    ((映射)newValues.getStoredSnapshot()).keySet()
    :null;
    System.out.println(“所有者:”+(所有者!=null?所有者.toString():“(null)”);
    System.out.println(“oldValues:”+(oldValues!=null?oldValues.toString():“(null)”);
    System.out.println(“newValues:”+(newValues!=null?newValues.toString():“(null)”);
    }else if(PersistentSet的集合实例){
    PersistentSet newValues=(PersistentSet)集合;
    对象所有者=newValues!=null?newValues.getOwner():null;
    设置oldValues=newValues!=null
    ((映射)newValues.getStoredSnapshot()).keySet()
    :null;
    System.out.println(“所有者:”+(所有者!=null?所有者.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领域,或者我会为您尝试一下:)

    如果您不重写standart nhibernate集合(列表、集合、映射),您总是可以获得集合的初始内容(在任何更改之前保存在base中的内容)。列表示例:

    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
    }
    

    当然,您可以确定哪些元素已被添加、删除或保持不变。

    我真的看不出这对我有什么帮助。例如,如果我们使用博客数据模型,我在检测普通对象属性(仅在集合中)的更改时不会遇到问题,并且集合的Add和Remove方法不会在代理上调用(同样,这在非延迟加载的对象上也不起作用),当有人调用post.Comments.Add时,会在代理上调用getter属性,并且可以被它捕获-但这并没有告诉我调用了Add(据我所知,它可能是来自foreach循环的GetEnumerator)它并没有告诉我添加了什么。为什么不能将快照内容与实际的持久收集内容进行比较?
    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)"));
        }
    }
    
    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
    }