NHibernate:更改父级 - “已删除的对象将通过级联重新保存”

时间:2015-01-23 16:38:05

标签: c# nhibernate mapping cascade orphan

正如标题所说,基本上我想做的就是改变一个孩子的父母。但是当我尝试这样做时,我得到了异常" ObjectDeletedException:删除的对象将通过级联重新保存(从关联中删除已删除的对象)"。

我现在谷歌搜索了几个小时,但我找到的解决方案都没有为我工作!!

这些是我的课程:

public class Parent: Entity
{
    public virtual IList<Child> Children { get; set; }
}

public class Child: Entity
{
    public virtual DateTime? CancellationDate { get; set; }
}

类Entity是具有Id属性的类。

这是父母的映射(Parents.hbm.xml):

<bag name="Children" cascade="all-delete-orphan" table="Schema.Child" where="CancellationDate is null">
  <key column="ParentID"/>
  <one-to-many class="Namespace.Child"/>
</bag>

这是我尝试将孩子重新分配给另一位家长的代码:

foreach(Child c in Parent1.Children)
{
    Parent2.Children.Add(c);
}

但是,session.Flush()抛出了上面的异常。 我想问题是因为Child改变了他的父级,因为级联NHibernate必须消除Child,但是之后它已被重新设置为另一个父级,所以,再次因为级联,它将不得不重新保存孩子。

我已经尝试更改映射,并将Child从前父集合中移除(在我将其分配给另一个父级之前或之后),但这些都不起作用......

任何帮助都将非常感谢!!

谢谢!

3 个答案:

答案 0 :(得分:0)

我已经看到了你的免责声明: ...我一直在谷歌搜索几个小时,但我找到的解决方案都没有为我工作!!

但总的来说,上面的示例只是从不能够(重新)生成ObjectDeletedException

在nhibernate中甚至还有一个内置测试,它检查:

NHibernate.Test.NHSpecificTest.NH1531 SampleTest ReparentingShouldNotFail

[Test]
public void ReparentingShouldNotFail()
{
    FillDb();
    using ( ISession session = OpenSession() )
    {
        var parent1 = session.Get<Parent>(1);
        var parent2 = session.Get<Parent>(2);

        Assert.AreEqual(1, parent1.Children.Count);
        Assert.AreEqual(0, parent2.Children.Count);

        Child p1Child = parent1.Children[0];

        Assert.IsNotNull(p1Child);

        parent1.DetachAllChildren();
        parent2.AttachNewChild(p1Child);

        session.Update(parent1);
        session.Update(parent2);

        // NHibernate.ObjectDeletedException : 
        // deleted object would be re-saved by cascade 
        // (remove deleted object from associations)
        // [NHibernate.Test.NHSpecificTest.NH1531.Child#0]

        session.Flush();
    }
    ...

这个测试正在通过。

那么问题出在哪里?只是在你没有显示的代码中的somwhere。有关此类问题的详细说明,请访问:

还有一些讨论和更多提示

ObjectDeletedException (“已删除的对象将被重新保存...”)几乎总是意味着:某些对象已被删除。这是存储在当前session中的信息。但仍有一些集合引用它......

答案 1 :(得分:0)

某种程度上我无法访问我提出问题的帐户。

事实证明,我们不会在逻辑上删除数据,因此将级联更改为“save-update”可以解决问题。

这个链接非常清楚地解释了NHibernate中重新定位的问题:

http://osdir.com/ml/nhusers/2009-09/msg00323.html

答案 2 :(得分:0)

我知道它已经有一段时间了,我不知道你是否仍然需要这个,但我最近遇到了这个问题,这里有一个对我有用的代码片段:

parent.Children.Remove(child);
session.Delete(child);
session.Evict(child);
child.ID = 0;
child.Parent = otherParent;
otherParent.Children.Add(child);

基本上,这会删除旧子项并添加一个全新的ID,并为另一个父项添加相同的属性。这可以防止您必须创建子对象的深层副本以将其添加到新父对象。它正在做的是取消孩子与其旧父母的关联,删除它(从会话),驱逐它(迫使nhibernate忘记对象的存在),重置ID(假设你使用sql种子身份列),重新养育它然后将其添加到新父母的集合中。

使用这种策略,我仍然可以在父映射上保留“cascade-all-delete-orphan”,而不必使关系“反向”。希望这有助于任何人解决这个问题,这可能是一个真正的痛苦......