Nhibernate 多对一,全部删除孤立项,将属性设置为null,但未删除实体
使用NHibernateV3.0。我有一个类似的课程: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
class Foo
{
bool barActive;
Bar bar;
}
Bar实例完全由Foo内部管理:
<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()
,因此不要使其成为瓶颈).amulti-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票,我认为是相关的,但是你可以为你的问题专门打开另一张。