Search code examples
fluent-nhibernate

NHibernate persist order for adding object to collection


I'm probably making a newbie mistake here, but I can't figure out how to make this work. I have two entities - Parent and Child, where one Parent can have many Children. The problem seems to be that when I add a new child to a parent, the parent can't cascade save the child, because the child instance doesn't have an ID yet. On the other hand, the child can't be persisted on its own, so it has no way of getting an ID...

My mappings:

public ParentMap()
{ 
    // ID and other properties

    HasMany(p => p.Children).Cascade.AllDeleteOrphan().Not.LazyLoad();
}

public ChildMap()
{
    // ID and other properties

    References(c => c.Parent);
}

Now, I might already have a parent record in my database, and I want to add a child to its collection of children. To do so, I create a new instance of the Child class, add the child to the parent's Children property (of type IList<Child>). I also fetch the parent record and sets the childs Parent property to the parent entity.

When I try to save this, I get errors no matter which order I try to do it.

With Save(p), saving the parent record and hoping the child will be saved on cascade, I get the following error:

Cannot insert the value NULL into column 'ChildID', table 'dbo.Children'; column does not allow null values. INSERT fails. The statement has been terminated.

If I try the other way around, i.e. first saving the child, then adding it to the parent and saving the parent, I get the following error:

null id in Application.Domain.Entities.Child entry (don't flush the Session after an exception occurs)

In what order should I call parent.Children.Add(child), child.Parent = parent, session.Save(parent), and session.Save(child) to make this work? Is something missing in my mapping configuration?

Update: I've added .Inverse(), and tried the following without success:

// First of the above errors
session.Save(child);
child.Parent = parent;
parent.Children.Add(child);
session.Save(parent);

// Second of the above errors
child.Parent = parent;
parent.Children.Add(child);
session.Save(child);
session.Save(parent);

// Second of the above errors
child.Parent = parent;
parent.Children.Add(child);
session.Save(parent);

// Second of the above errors
child.Parent = parent;
parent.Children.Add(child);
session.Save(child);

Solution

  • Turns out the problem wasn't with NHibernate at all, but rather with my database configuration - I had forgotten to configure the ID column of the Children table. As soon as I specified the ID column, everything worked as expected: no .Inverse() needed, and I could save just the Parent and the Child is saved on cascade.