Search code examples
nhibernatetreeselfbag

NHibernate mapping - self referencing: parent and children


I am trying to have this kind of Model:

public class Activity
{
    public virtual int ID { get; set; }

    public virtual int? ParentID { get; set; }
    public virtual int? RootID { get; set; }

    public virtual Activity Parent { get; set; }
    public virtual Activity Root { get; set; }
    public virtual IList<Activity> Children { get; set; }
}

If you are looking at it from a structure point of view, it is a tree. The root element does not have a parent or a root, but may have children. Any of its children must have a parent and a root (for the first level children root = parent)

The mapper is like this:

public class ActivityMap : ClassMapping<Activity>
{
    public ActivityMap()
    {
        Table("activity");
        Lazy(true);
        Id(x => x.ID, map => map.Generator(Generators.Identity));

        ManyToOne(x => x.Root, map => { map.Column("RootID"); map.Cascade(Cascade.All); });

        Bag(x => x.Children,
           mapping =>
           {
               mapping.Inverse(false);
               mapping.Lazy(CollectionLazy.Lazy);
               mapping.Key(k => k.Column("ParentID"));
               mapping.Cascade(Cascade.All);
           },
           mapping => mapping.ManyToMany(map=>map.Class(typeof(Activity)))
           );
    }
}

The problem is when I try to fetch the children, the sql statement looks like:

SELECT children0_.ParentID as ParentID1_,
children0_.elt as elt1_, 
activity1_.ID as ID55_0_, 
activity1_.TaskID as TaskID55_0_, 
activity1_.ActivityTypeID as Activity3_55_0_, 
activity1_.StateID as StateID55_0_, 
activity1_.Continueforward as Continue5_55_0_, 
activity1_.Ordernumber as Ordernum6_55_0_, 
activity1_.IsDeleted as IsDeleted55_0_, 
activity1_.Created as Created55_0_, 
activity1_.Modified as Modified55_0_, 
activity1_.StartTime as StartTime55_0_, 
activity1_.EndTime as EndTime55_0_, 
activity1_.Progress as Progress55_0_, 
activity1_.RootID as RootID55_0_ 
FROM Children children0_ left outer join activity activity1_ on children0_.elt=activity1_.ID WHERE children0_.ParentID=?
  1. First of all it seems that it is looking for the Children table which does not exist. Should be Activity table
  2. Second: I am not sure what is with that "elt" column... it does not exist anywhere

Anyone has an idea how to make this mapping?

Later Edit: found in answer to the second question: NHibernate elt field


Solution

  • In my later edit I have the answer to my second question.

    And for the second question, the solution that I found is to give up to the relation with the Root entity

    ManyToOne(x => x.Root, map => { map.Column("RootID"); map.Cascade(Cascade.All); });
    

    and replace it with

    Property(x => x.RootID);
    

    because I have no need to have the entire entity for the Root. Also I have changed the bag for Children like this:

    Bag(x => x.Children,
               mapping =>
               {
                   mapping.Inverse(false);
                   mapping.Lazy(CollectionLazy.Lazy);
                   mapping.Key(k => k.Column("ParentID"));
                   mapping.Cascade(Cascade.All);
               },
               mapping => mapping.OneToMany()
               );