10

The title pretty much explains it all, I have a Member object that references 'Friends' who are also type Member.

public class Member : Entity
    {
        public Member()
        {            
            Friends = new List<Member>();
        }

        public virtual IList<Member> Friends
        {
            get; set;
        }
     }

The schema generation tool makes it a 1:n relationship while it should be a n:n relationship i.e. a column is added to the member table called member_id and no connecting table is created.

Is there any way to make a Self referencing many to many relationships in Fluent NHibernate?

I tried using an override that I got as an answer before:

public class MemberOverride : IAutoMappingOverride<Member>
{
    public void Override(AutoMapping<Member> mapping)
    {
        mapping.HasManyToMany(m => m.Friends)
               .Table("MemberFriendsLinkTable");
    }
}

but I get the error message:

"NHibernate.MappingException: Repeated column in mapping for collection: Proj.BO.Member.Friends column: Member_id"

Thanks

EDIT: I found the answer, it's to put:

mapping.HasManyToMany(m => m.Friends).ParentKeyColumn("Member_Id").ChildKeyColumn("Friend_Id")
                   .Table("MemberFriendsLinkTable").Inverse().Cascade.SaveUpdate();
Daniel Schilling
  • 4,829
  • 28
  • 60
Eitan
  • 1,434
  • 6
  • 21
  • 53

3 Answers3

5

So that I don't have to see this question at the top of the "Unanswered NHibernate Questions" list anymore...

Eitan, the asker, discovered the solution to his own problem. He needed to specify the ParentKeyColumn and ChildKeyColumn like so:

EDIT: I found the answer, it's to put:

mapping.HasManyToMany(m => m.Friends)
    .ParentKeyColumn("Member_Id")
    .ChildKeyColumn("Friend_Id")
    .Table("MemberFriendsLinkTable")
    .Inverse()
    .Cascade.SaveUpdate();

FluentNHibernate by default names foreign key columns like so: {className}_Id. Since both ends of the many-to-many were of the same type, it wanted to use the same column name, Member_Id for both columns. Explicitly naming the columns circumvents this problem.

Daniel Schilling
  • 4,829
  • 28
  • 60
  • 1
    I found that adding either `ParentKeyColumn` or `ChildKeyColumn` is sufficient (if you provide a name different from the default of course) – Stefan Paul Noack Feb 02 '12 at 19:36
  • 1
    The `.Inverse()` actually throw an exception in my case so I had to remove it, but apart from that this solution works wonderfully! – Oliver Jun 16 '14 at 20:40
0
References(x => x.Parent)
            .Class<Parent>()
            .Access.Property()
            .Cascade.None()
            .LazyLoad()
            .Not.Insert()
            .Not.Update()
            .Columns("PARENT_ID");

        HasMany(x => x.Children)
          .Access.Property()
          .AsBag()
          .Cascade.SaveUpdate()
          .LazyLoad()
          .Inverse()
          .Generic()
          .KeyColumns.Add("PARENT_ID", mapping => mapping.Name("PARENT_ID")
                                                               .SqlType("NUMBER")
                                                               .Not.Nullable());
MJP
  • 59
  • 1
  • 1
0

Well I understand that, I have similar kind of issue with little bit of change. Can you please try to answer the question to the link

Fluent nhibernate m-to-m mapping with external table

Community
  • 1
  • 1
DSam
  • 51
  • 1
  • 7