简体   繁体   中英

EF6 code first Many to Many with additional property of the same type as the collection on one of the entities

I know this issue has many similar questions here on SO, but I couldn't find one that's exactly like mine, but I might be wrong and there exists one. So here's my question:
We have two entities (C# poco classes), Meeting and User , that each one of them contains a collection of the other entity. Code, shortened for brevity:

public class Meeting
{
    public int ModeratorId { get; set; }
    public virtual User Moderator { get; set; }    // Property of type User

    public virtual ICollection<User> Participants { get; set; } // Collection of User
}

And here's the second one:

public class User
{
    public virtual ICollection<Meeting> Meetings { get; set; }
}  

Now, when adding a migration, one would expect that EF would create a linking table, something like MeetingUsers , which it actually creates if I omit the Moderator property. But when I add the Moderator property, that is the same type as the items in Participants , EF removes the linking table and adds a Meeting_Id column in the migration. Here are the migrations:
first migration, with only the collections on the two classes, without the additional Moderator property on Meeting :

public override void Up()
    {   
        CreateTable(
            "dbo.MeetingUsers",
            c => new
                {
                    Meeting_Id = c.String(nullable: false, maxLength: 128),
                    User_ID = c.Int(nullable: false),
                })
            .PrimaryKey(t => new { t.Meeting_Id, t.User_ID })
            .ForeignKey("dbo.Meetings", t => t.Meeting_Id, cascadeDelete: true)
            .ForeignKey("dbo.Users", t => t.User_ID, cascadeDelete: true)
            .Index(t => t.Meeting_Id)
            .Index(t => t.User_ID);
        
    }  

You can see that EF creates the linking table just fine (I omitted the Meeting and User for brevity).
And here's the second migration EF adds after I add the Moderator property:

public override void Up()
    {
        DropForeignKey("dbo.MeetingUsers", "Meeting_Id", "dbo.Meetings");
        DropForeignKey("dbo.MeetingUsers", "User_ID", "dbo.Users");
        DropIndex("dbo.MeetingUsers", new[] { "Meeting_Id" });
        DropIndex("dbo.MeetingUsers", new[] { "User_ID" });
        AddColumn("dbo.Users", "Meeting_Id", c => c.String(maxLength: 128));
        AddColumn("dbo.Meetings", "ModeratorId", c => c.Int());
        AddColumn("dbo.Meetings", "User_ID", c => c.Int());
        CreateIndex("dbo.Users", "Meeting_Id");
        CreateIndex("dbo.Meetings", "ModeratorId");
        CreateIndex("dbo.Meetings", "User_ID");
        AddForeignKey("dbo.Meetings", "ModeratorId", "dbo.Users", "ID");
        AddForeignKey("dbo.Users", "Meeting_Id", "dbo.Meetings", "Id");
        AddForeignKey("dbo.Meetings", "User_ID", "dbo.Users", "ID");
        DropTable("dbo.MeetingUsers");
    }  

As you see EF removed the linking table and adds a column on the Users table, which is not what I want. I want instead to keep the linking table and just add a new column ModeratorId to the Meetings table.
How do I achieve that? I might add that we use data annotations throughout and not the fluent api of EF.

Thanks,
ashilon

You can define manually link table and you are good to go.

 public class Meeting
 {
    public int ModeratorId { get; set; }
    public virtual User Moderator { get; set; }    // Property of type User


}

And here's the second one:  

public class User
{
    .....
} 
public MeetingUser{

   public int UserId{get;set;}
   public virtual User User{get;set;}
   public int MeetingId {get;set;}
   public virtual Meeting Meeting {get;set;}
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM