Wednesday, December 19, 2012

NHibernate Inverse and Cascade

Best explanation: http://www.emadashi.com/2008/08/nhibernate-inverse-attribute/

Suppose we have a Parent with a collection of Child objects (one to many)

public class Parent

{

public virtual int Id { get; set; }

public virtual string Name { get; set; }

public virtual IList<Child> MyChildren { get; set; }

}

public class Child

{

public virtual int Id { get; set; }

public virtual string Name { get; set; }

public virtual Parent MyParent { get; set; }

}

 

Parent par = Session.Get<Parent>(8);

Child ch = new Child();

ch.Name = “Emad”;

par.MyChildren.Add(ch);

Session.Save(par);

 

First, we need to set the cascade on the MyChildren, such that when ever you save the Parent, all the Child objects in the MyChildren collection are forced to be saved as well.

Also, by default, the parent object will also set the ParentId column on the newly inserted Child, because there is a hidden property on the MyChildren collection which is by default false. This means the Parent object will manage the relationship by updating the ParentId foreign key on the child row.

So what will happen is:

1. the new child is added

2. the new child ParentId foreign key is updated

The problem comes when you put the null constraint on the MyParent, the insert will fail because the ParentId is not yet set.

To overcome the issue, the solution is to:

1. set inverse attribute to false for the MyChildren collection. this will not update the ParentId foreign key anymore on the Child

2. explicitly set the Parent property in code for the Child object

Parent par = Session.Get<Parent>(8);

Child ch = new Child();

ch.Name = “Emad”;

ch.MyParent = par;

par.MyChildren.Add(ch);

Session.Save(par);

No comments: