views:

59

answers:

1

I have two entities:

public class Parent()
{
    public ICollection<Child> Children { get; set; }
}

public class Child()
{
    public Parent Parent { get; set; }
}

The mapping looks like so:

public class ParentMap : ClassMap<Parent>
{
    HasMany(x => x.Children).Cascade.All().Inverse();
}

public class ChildMap : ClassMap<Child>
{
    References(x => x.Parent).Cascade.None();
}

Normally, in order to save a parent or a child, you'd have to do something like this:

var parent = new Parent();
var child = new Child();

parent.Children.Add(child);
child.Parent = parent;

Session.SaveOrUpdate(parent);

In other words, you have to set the properties in both objects in order for NHibernate to persist this entity correctly.

However, for legacy issues, I'd like to save this entity without having to set both sides, so that I can just do:

var parent = new Parent();
var child = new Child();
child.Parent = parent;

Session.SaveOrUpdate(child);

In this case, I don't add the child to the parent's Children collection, I just set the Parent on the child object.

Is there any way to get NHibernate to persist this correctly so that when I grab the parent out of the database, it will have the child inside its Children collection?

P.S. I realize that there's a potential issue here with the session cache and relying on NHibernate to perform some behind-the-scenes operations to make the data model correct, but I'm ignoring this issue for now.

+1  A: 

Map Parent as a private field in Child:

public class ChildMap : ClassMap<Child>
{
    References(x => x.Parent).Cascade.None()
        .Access.CamelCaseField(Prefix.Underscore);
}

and control it through the public property:

public class Child()
{
    private Parent _parent;

    public Parent Parent
    {
        get { return _parent; }
        set
        {
            _parent = value;
            _parent.Children.Add(this);
        }
    }
}

But the code you have now should work as expected. You don't have to add the Child to the Parent's Children collection to get NH to persist it because it's marked as the inverse side of the relationship. You add it to keep the in-memory objects in sync with the database. If you set the Parent on the Child, flush the session, and re-load the parent in a new session then the Children collection should contain the child (assuming 2nd level cache doesn't come into play).

Edit: To add the child to the parent, encapsulate the action in a method:

public void AddChild(Child child)
{
    _children.Add(child);
    child.Parent = this;
}
Jamie Ide
I managed to get the child to save correctly without establishing the Parent. In the mapping, I have to set `KeyColumn` on the many side and `Column` on the one side to the same string in order to get it to work.
Daniel T.
However, this brings up a second question: now that I can save the child and have the relationship work correctly, is there a way to do the opposite and add the child to the parent's `Children` collection, and then save it without having to set the child's `Parent` property?
Daniel T.
See my edit. I'd appreciate an upvote if this was helpful.
Jamie Ide
There ya go, thanks :).
Daniel T.