Roar
Roar

Reputation: 2167

Fluent NHibernate HasMany mapping inserts null in foreign key

I have 2 entities:

public class Parent
{
    public virtual string Number { get; set; }
    public virtual IList<Child> Children { get; set; }
    public Parent()
    {
        Phones = new List<Child>();
    }
}
public class Child
{
    public virtual string Number { get; set; }
    public virtual Parent Parent { get; set; }
}

and mappings:
child

 public ChildMap()
        {
            Map(x => x.Number).Not.Nullable();
            References(x => x.Parent).Nullable().LazyLoad().Cascade.None();
        }

and parent

public ParentMap()
    {
        Map(x => x.Number).Not.Nullable();
        HasMany(x => x.Children).Inverse().Cascade.All();
    }

but when i insert children to parent, it goes with null in parent foreign key.

var p = rep.Get(g => g.Id == 1);
Enumerable.Range(0, 100).Select(s => new Child()
    {
        Number = s.ToString()
    }).ToList().ForEach(p.Children.Add);
rep.Update(p);
rep.Flush();

actualy everything like in post NHibernate fluent HasMany mapping inserts NULL Foreign key
But insert link like this test.Orders.Add(new Order("test") { Company = test }); absolutly not true way, so i need help, any ideas?

Upvotes: 0

Views: 4752

Answers (3)

Roar
Roar

Reputation: 2167

The answer is

public ParentMap()
    {
        Map(x => x.Number).Not.Nullable();
        HasMany(x => x.Children).Cascade.All();
    }

Without inverse

Upvotes: 0

Russ Cam
Russ Cam

Reputation: 125538

You have a bidirectional relationship set up between Parent and Child, but when you are adding a child to the Children collection on Parent, you are not setting the Parent property on each child.

The first thing I would recommend is question whether the relationship needs to be bidirectional - will typical usage work with Children independent of their Parents? Would you need to navigate the object graph in the direction from Child to Parent? Are both Parent and Child Aggregate Roots?

There are a few different ways to handle bidirectional relationships. One way is to define Add and Remove methods that add a Child to the Children collection and sets the Parent property on each child and to remove the ability to add a child directly to the collection, by making it an IEnumerable<Child> (or IReadOnlyCollection<Child>, or similar) for example with an IList<Child> backing field

public class Parent
{
    private IList<Child> _children;

    public Parent()
    {
        _children = new List<Child>();
    }

    public virtual string Number { get; set; }
    public virtual IEnumerable<Child> Children { get { return _children; } }

    public virtual void AddChild(Child child)
    {
        _children.Add(child);
        child.Parent = this;
    }

    public virtual void RemoveChild(Child child)
    {
        _children.Remove(child);
        child.Parent = null;
    }
}

public class Child
{
    public virtual string Number { get; set; }
    public virtual Parent Parent { get; set; }
}

The ParentMap should be modified to use the backing field

public ParentMap()
{
    Map(x => x.Number).Not.Nullable();
    HasMany(x => x.Children).Inverse()
                            .Cascade.All()
                            .Access.CamelCaseField(Prefix.Underscore);
}

Upvotes: 1

mehdi.loa
mehdi.loa

Reputation: 575

change to:

Enumerable.Range(0, 100).Select(s => new Child()
    {
        Number = s.ToString(),
        Parent = p
    }).ToList().ForEach(p.Children.Add);

Upvotes: 0

Related Questions