Search code examples
c#sqlentity-frameworkfluent

Fluent API - how to map custom relation table?


I have class which may look like this:

public class Group
{
    public int Id {get; set;}
    public ICollection<Group> IsMemberOf {get; set;}
}

Group can be member of other groups. Id db I have table Group and table GroupGroup. In ModelBuilder I use this code to define mapping.

modelBuilder.Entity<GroupGroup>()
            .ToTable("GroupGroup")
            .HasKey(e => new { e.GroupId, e.MemberGroupId });
modelBuilder.Entity<Group>()
            .ToTable("Group")
            .Ignore(e => e.IsMemberOf);

Well, my question is how to map groups from relation table GroupGroup to property IsMemberOf with Fluent API? I am very new to ef, Fluent API and such and I know I should let ef to create its own relation table, but I must use this way because of connection to AD and other systems. Is there any way how achieve this?

Thanks a lot for any hint.


Solution

  • Looks like you need a many-to-many association, because of this GroupGroup association table. One way to map this is:

    modelBuilder.Entity<Group>()
        .HasMany(g => g.IsMemberOf)
        .WithMany()
        .Map(m => m.MapLeftKey("ChildGroupId")
                   .MapRightKey("GroupId")
                   .ToTable("GroupGroup")
            );
    

    That means that you don't have a GroupGroup entity class in your class model. EF populates the IsMemberOf collection by setting up all necessary joins if you execute a LINQ statement like:

    var groups = context.Groups.Include(g => g.IsMemberOf).ToList();
    

    I don't know why you have this line .Ignore(e => e.IsMemberOf) in your mapping, but that should be deleted.

    You can even make the mapping go both ways:

    public class Group
    {
        public int Id {get; set;}
        public ICollection<Group> IsMemberOf { get; set; }
        public ICollection<Group> HasMembers { get; set; }
    }
    

    And the mapping:

    modelBuilder.Entity<Group>()
        .HasMany(g => g.IsMemberOf)
        .WithMany(g => g.HasMembers)
        .Map(m => m.MapLeftKey("ChildGroupId")
                   .MapRightKey("GroupId")
                   .ToTable("GroupGroup")
            );