Inserting parent and children with NHibernate at the same time

fluent-nhibernatenhibernate

I am attempting to save(insert) a Parent entity with list Child entities. Both entites use a Guid as primary keys. The keys are none nullable and there is no key relationship set up in the db.

The save doesn't work, an exception is thrown claiming – that I am trying to save a null into Parent foreign key in the Child table.

I was expecting nhibernate to create a key for the Parent and let its Child objects know about it. Is this a limitation of NHibernate or of using Guids as primary keys?

This answer suggests you have to set the parent manully, is this really the only way?

Here are my mappings for reference:

Parent mapping:

HasMany(x => x.Children).KeyColumn("ParentKey").Inverse().Cascade.All();

Child mapping:

 References(x => x.Parent).Not.Nullable().Column("ParentKey");

Best Answer

NHibernate is not magic. It is only an ORM, if your children do not have their reference set to the parent, why would it assume that because the parent has a list of children that the childrens' reference, in turn, SHOULD be a reference to the parent?

I believe you answered your own question when you stated that the Child entities don't have their Parent property populated (which means it is null, which means NHibernate would be attempting to save a 'null' value for the Parent id in your Child table).

If you were to use these objects WITHOUT NHibernate it would make sense that the Parent reference needs to be set on the Child entities when they are added.

EDIT: This is for the case where you have specified 'Inverse' on your mapping. If you were to remove this call to 'Inverse,' it should work the way you wanted it to work as Inverse states that the other end (the child entity) is responsible for keeping track of the relationship. This means you need to set the reference of the parent on the child manually.

However, removing the Inverse statement would cause the Child(ren) to be saved, the parent to be saved, then the Child(ren)'s parent id to be UPDATED. Since you have a null constraint on the parent id, this means it still won't work as it would initially insert the Child with a parent id of null.

The two solutions would be to either remove this constraint, or to just add a method to the Parent called AddChild:

public void AddChild(Child childObj)
{
    childObj.Parent = this;
    Children.Add(childObj);
}

Add another method called RemoveChild:

public void RemoveChild(Child childObj)
{
    if (Children.Contains(childObj))
    {
        Child.Parent = null;
        Children.Remove(childObj);
    }
}

Then, just use those methods for adding/removing children.

Related Topic