2

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

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

这些是我参与的课程:

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

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

实体类是具有 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()抛出了上面的异常。我想问题是因为孩子改变了他的父母,因为级联NHibernate将不得不消除孩子,但后来它被重新分配给另一个父母,所以再次因为级联,它必须重新保存孩子。

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

任何帮助将不胜感激!

谢谢!!

4

3 回答 3

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();
    }
    ...

这个测试通过了。

那么,问题出在哪里?只是在您没有显示的代码中的某个地方。可以在此处找到此类问题的详细描述:

还有一些讨论和更多提示

( ObjectDeletedException "deleted object will be re-saved...")几乎总是意味着:某个对象已被删除。那是存储在 current 中的信息session。但是仍然有一些集合引用它......

于 2015-01-24T07:04:53.890 回答
0

不知何故,我无法访问我提出问题的帐户。

事实证明,我们不会在物理上擦除数据,只是在逻辑上,因此将级联更改为“保存更新”解决了问题。

此链接非常清楚地解释了 NHibernate 中的重新父母问题:

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

于 2015-03-05T22:39:02.900 回答
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”,而不必使关系“反向”。希望这可以帮助任何人解决这个问题,这可能是一个真正的痛苦......

于 2016-03-16T16:06:17.367 回答