2

As the title says, basically what I want to do is to change a child's parent. But when I try to do so, I get the exception "ObjectDeletedException: deleted object would be re-saved by cascade(remove deleted object from associations)".

I've been googling for hours now but none of the solutions I found worked for me!!

These are my classes involved:

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

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

The class Entity is the one that has the Id property.

This is the parent's mapping (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>

And this is the piece of code where I try to reasign the child to another parent:

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

But then, the session.Flush() throws the exception above. I guess that the problem is that since the Child changed his parent, because of the cascade NHibernate would have to eliminate the Child, but then it has been reasigned to anothet parent so, again because of the cascade, it would have to re-save the Child.

I already tried changing the mapping, and removing the Child from the former parent's collection (before or after I assign it to the other parent) but none of those worked...

Any help would be very appreciated!!

Thanks!!

  • as a possible solution, try to add COPIES of parents1 childs to parent2. be aware, this will create (after save) new records in db associated with parent2 and remove rows of parent1 childs. Or you just want to update ParentId? – ASh Jan 23 '15 at 17:06
  • Yeah, I thought about that solution, but I can't create a new one, the Child's Id has to stay the same... Thanks anyway!! – Natan Menoni Jan 23 '15 at 17:11
  • is it helpful? http://stackoverflow.com/questions/2763985/how-do-i-change-a-childs-parent-in-nhibernate-when-cascade-is-delete-all-orphan – ASh Jan 23 '15 at 17:22

3 Answers3

0

I have seen your disclaimer: ...I've been googling for hours now but none of the solutions I found worked for me!!

But In general, the example above is simply never able to (re)produce the ObjectDeletedException.

There is even a built in test in nhibernate, which check that:

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

This test is passing.

So, where is the issue? simply somwhere in the code which you did not shown. The detailed description of such issue could be found here:

And also some discussion and more hints here

The ObjectDeletedException ("deleted object would be re-saved...") almost always means: Some object was DELETED. That is information stored in current session. But there is still some collection referencing it...

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
0

somehow I can't access the account with which I asked the question.

Turns out that we don't phisically erase the data, only logically, so changing the cascade to 'save-update' solved the problem.

This link explains very clearly the issue of reparenting in NHibernate:

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

Natan Menoni
  • 41
  • 1
  • 6
0

I know its been a while and I don't know if you still need this, but I recently ran into this issue and here's a code snippet that worked for me:

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

Basically, this deletes the old child and adds a brand new one with a new ID and the same properties to the other parent. This prevents you from having to make a deep copy of the child object to add it to the new parent. What it's doing is disassociating the child from its old parent, deleting it (from session), evicting it (forcing nhibernate to forget the object's existence), resetting the ID (assuming you are using a sql seeded identity column), re-parenting it then adding it to the new parent's collection.

Using this tactic, I'm still able to keep "cascade-all-delete-orphan" on the parent mapping, while not having to make the relationship "inverse". Hope this helps anyone going through this issue, it can be a real pain...

Nautic20
  • 215
  • 4
  • 15