ASP.NET Core EF Many to Many referencing table

asp.net asp.net-core c# entity-framework-core

Question

I'm trying to create a user with contacts table. I'm not sure if I'm doing it the right way as there is a column added which I didn't declare.

The entities:

public class User
{
    public int Id { get; set; }
    public bool IsAvailable { get; set; }
    public List<Contact> Contacts { get; set; }
}

public class Contact
{
    public int UserId { get; set; }
    public int ContactUserId { get; set; }

    public User User { get; set; }
    public User ContactUser { get; set; }
}

The mapping:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Contact>()
        .HasKey(x => new { x.UserId, x.ContactUserId });

    modelBuilder.Entity<Contact>()
        .HasOne(x => x.User)
        .WithMany(x => x.Contacts)
        .HasForeignKey(x => x.UserId);

    modelBuilder.Entity<Contact>()
        .HasOne(x => x.ContactUser)
        .WithMany(x => x.Contacts)
        .HasForeignKey(x => x.ContactUserId);
}

The result:

migrationBuilder.CreateTable(
    name: "Contact",
    columns: table => new
    {
        UserId = table.Column<int>(nullable: false),
        ContactUserId = table.Column<int>(nullable: false),
        UserId1 = table.Column<int>(nullable: true)
    },
    constraints: table =>
    {
        table.PrimaryKey("PK_Contact", x => new { x.UserId, x.ContactUserId });
        table.ForeignKey(
            name: "FK_Contact_User_ContactUserId",
            column: x => x.ContactUserId,
            principalTable: "User",
            principalColumn: "Id",
            onDelete: ReferentialAction.Cascade);
        table.ForeignKey(
            name: "FK_Contact_User_UserId1",
            column: x => x.UserId1,
            principalTable: "User",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    });

The real question:

Where is the column UserId1 in contact coming from? Is there something wrong with my definition? Thanks!

1
0
5/24/2016 4:41:11 PM

Accepted Answer

The reason you ended up with an additional UserId1 on contact table is because you are specifying the other side of both User and ContactUser associations on Contact object to be Contacts on User object which is incorrect. As a result, EF ignores it and creates yet another association for Contacts on User object and map it to UserId1 column on Contact table.

One way to fix this is to create another list of Contacts on User object and map it accordingly:

public class User
{
    public int Id { get; set; }
    public bool IsAvailable { get; set; }

    public List<Contact> Contacts { get; set; }
    public List<Contact> ContactUsers { get; set; }
}

modelBuilder.Entity<Contact>()
    .HasOne(x => x.User)
    .WithMany(x => x.Contacts)
    .HasForeignKey(x => x.UserId);

modelBuilder.Entity<Contact>()
    .HasOne(x => x.ContactUser)
    .WithMany(x => x.ContactUsers)
    .HasForeignKey(x => x.ContactUserId)
    .OnDelete(DeleteBehavior.Restrict);


Which yields the desired schema:

enter image description here

2
5/24/2016 8:23:39 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow