Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Nhibernate 多对一,全部删除孤立项,将属性设置为null,但未删除实体_Nhibernate - Fatal编程技术网

Nhibernate 多对一,全部删除孤立项,将属性设置为null,但未删除实体

Nhibernate 多对一,全部删除孤立项,将属性设置为null,但未删除实体,nhibernate,Nhibernate,使用NHibernateV3.0。我有一个类似的课程: class Foo { bool barActive; Bar bar; } Bar实例完全由Foo内部管理: 当“barActive”为true时,“bar”设置为bar实例 当“barActive”设置为false时,“bar”字段设置为null Foo.bar的映射方式如下: <many-to-one name="bar" column="BarId" cascade="all-delete-orphan" uniqu

使用NHibernateV3.0。我有一个类似的课程:

class Foo
{
  bool barActive;
  Bar bar;
}
Bar实例完全由Foo内部管理:

  • 当“barActive”为true时,“bar”设置为bar实例
  • 当“barActive”设置为false时,“bar”字段设置为null
  • Foo.bar的映射方式如下:

    <many-to-one name="bar" column="BarId" cascade="all-delete-orphan" unique="true" />
    
    
    
    但是,当“bar”设置为null时,它不会删除数据库中的bar记录。Bar是一个继承的类,在其他地方也使用它,所以我不能仅仅将这个字段作为一个组件


    我希望“唯一”约束+删除孤立项可以处理这个问题。我遗漏了什么,或者NHibernate不能透明地处理这个问题吗?如果不能,我唯一的选择似乎是引发一个事件,以便更高级别的作用域可以调用ISession.Delete(bar)。

    我有一个解决方法,可以自动删除孤立项。我相信它应该适用于NHibernate版本3和更高版本。它使用一个拦截器——基本上是一个处理各种会话相关事件的对象。当它检测到
    Foo
    上的更新操作时,它将为孤立的
    添加一个显式删除

    using System;
    using System.Collections;
    using NHibernate;
    using NHibernate.Type;
    
    class Interceptor : EmptyInterceptor
    {
        private ISession _session;
        private Bar _barOrphan;
    
        public override void SetSession(ISession session)
        {
            base.SetSession(session);
            _session = session;
        }
    
        public override bool OnFlushDirty(object entity, object id, object[] currentStates, object[] previousStates, string[] propertyNames, IType[] types)
        {
            if (entity.GetType() != typeof(Foo)) return;
    
            for (var i = 0; i < propertyNames.Length; i++)
            {
                if (!StringComparer.Ordinal.Equals(propertyNames[i], "bar")) continue;
    
                object previousState = previousStates[i];
                if (currentStates[i] != previousState)
                {
                    _barOrphan = (Bar) previousState;
                }
                break;
            }
        }
    
        public override void PostFlush(ICollection entities)
        {
            if (_barOrphan == null) return;
    
            _session.Delete(_barOrphan);
            _barOrphan = null;
    
            _session.Flush();
        }
    }
    

    请注意,这只是一个草稿,用来解释这个概念(我希望我在重写代码时没有把代码弄糟;-)。在实际使用场景中,您可能需要处理在一个工作单元中创建的多个孤立项(同一实体上的事件,例如,
    Foo
    可能有
    bar1
    bar2
    !),因此,您需要在
    PostFlush()中执行的删除操作队列,而不是单个
    \u barOrphan
    成员
    。您不需要硬编码所涉及类的类型和属性的名称
    bar
    ,而是需要使用泛型和属性选择器(例如
    PropertySelector.GetPropertyName(foo=>foo.bar)
    ,请参阅.DB约束可能会出现问题,将删除操作移动到
    Interceptor.PreFlush()
    可能会有帮助,但我没有测试它。不要忘记性能影响(例如,
    OnFlushDirty()
    会为每个更新的实体调用,所以不要让它成为瓶颈).

    我有一个解决方法,可以自动删除孤立项。我相信它应该适用于NHibernate版本3及更高版本。它使用一个拦截器-基本上是一个处理各种会话相关事件的对象。当它检测到
    Foo
    上的更新操作时,它将为孤立的
    添加一个显式删除

    using System;
    using System.Collections;
    using NHibernate;
    using NHibernate.Type;
    
    class Interceptor : EmptyInterceptor
    {
        private ISession _session;
        private Bar _barOrphan;
    
        public override void SetSession(ISession session)
        {
            base.SetSession(session);
            _session = session;
        }
    
        public override bool OnFlushDirty(object entity, object id, object[] currentStates, object[] previousStates, string[] propertyNames, IType[] types)
        {
            if (entity.GetType() != typeof(Foo)) return;
    
            for (var i = 0; i < propertyNames.Length; i++)
            {
                if (!StringComparer.Ordinal.Equals(propertyNames[i], "bar")) continue;
    
                object previousState = previousStates[i];
                if (currentStates[i] != previousState)
                {
                    _barOrphan = (Bar) previousState;
                }
                break;
            }
        }
    
        public override void PostFlush(ICollection entities)
        {
            if (_barOrphan == null) return;
    
            _session.Delete(_barOrphan);
            _barOrphan = null;
    
            _session.Flush();
        }
    }
    

    请注意,这只是一个草稿,用于解释这个概念(我希望我在重写代码时没有弄糟代码;-)。在实际使用场景中,您可能需要处理在一个工作单元中创建的多个孤立项(同一实体上的事件,例如,
    Foo
    可能有
    bar1
    bar2
    !)因此,您需要在
    PostFlush()
    中执行的删除操作队列,而不是单个
    \u barOrphan
    成员。您需要使用泛型和属性选择器(例如
    PropertySelector.GetPropertyName),而不是对相关类的类型和属性的名称进行硬编码(foo=>foo.bar)
    ,请参阅.DB约束可能是个问题,将删除操作移动到
    Interceptor.PreFlush()
    可能会有帮助,但我没有对其进行测试。不要忘记性能影响(例如,为每个更新的实体调用
    OnFlushDirty()
    ,因此不要使其成为瓶颈).

    a
    multi-to-one
    mapping没有一个选项用于级联中的all-delete-orphan。只有
    all | none | save-update | delete
    。看看这里,为什么NHibernate接受的映射没有错误?在任何情况下,你有办法完成我想要的吗?据我所知,NHibernate没有办法自动完成ally为
    多对一关系删除一个孤立项,因为代码中没有对其进行检查。它将级联其他4个,如前所述。我认为有这个jira票据相关,但您可以针对您的问题专门打开另一个票据。
    多对一
    映射没有用于所有删除或删除的选项n在级联中。仅
    all | none | save update | delete
    。请参见此处,为什么NHibernate接受的映射没有错误?在任何情况下,您是否有办法完成我正在寻找的内容?据我所知,NHibernate无法自动删除
    多对一
    关系中的孤立项,因为没有che代码中的ck。它将级联其他4个,正如前面提到的。有一张jira票,我认为是相关的,但是你可以为你的问题专门打开另一张。