Entity Framework 代码优先,同一 table 上的多对多关系

Entity Framework code-first, Many-to-Many relationship on the same table

我正在构建一个具有好友功能的社交网络。 我的想法是我已经有了默认的 ApplicationUser class,所以我创建了一个名为 Friend

的新 table
public class Friend
{
    [Key]
    [Column(Order = 1)]
    public string SenderId { get; set; }

    [Key]
    [Column(Order = 2)]
    public string ReceiverId { get; set; }

    //Status == true : Friend request accepted
    //Status == false : Friend request not accepted
    public bool Status { get; set; }
}

ApplicationUser 中,我定义了 2 个导航属性 SendersReceivers(到 link 给朋友 table)

public class ApplicationUser : IdentityUser
{
    [Required]
    [StringLength(50)]
    public string Name { get; set; }

    [Required]
    public bool Gender { get; set; }

    [StringLength(255)]
    public string Address { get; set; }

    [StringLength(255)]
    public string Job { get; set; }

    [StringLength(255)]
    public string Image { get; set; }

    public DateTime Birthday { get; set; }

    public ICollection<ApplicationUser> Senders { get; set; }
    public ICollection<ApplicationUser> Receivers { get; set; }
}

最后在 ApplicationDbContext 中,我使用 Fluent Api

声明 2 table 之间的关系
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{

    public DbSet<Friend> Friends { get; set; }

    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {
    }

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<ApplicationUser>()
            .HasMany(a => a.Senders)
            .WithMany(a => a.Receivers)
            .Map(m =>
            {
                m.MapLeftKey("ReceiverId");
                m.MapRightKey("SenderId");
                m.ToTable("Friends");
            });
        base.OnModelCreating(modelBuilder);

    }
}

但是当我添加迁移时,它会像这样创建 2 个 table,但它们都不是我需要的(一个没有外键,一个没有 Status 属性)

public override void Up()
    {
        CreateTable(
            "dbo.Friends1",
            c => new
                {
                    SenderId = c.String(nullable: false, maxLength: 128),
                    ReceiverId = c.String(nullable: false, maxLength: 128),
                    Status = c.Boolean(nullable: false),
                })
            .PrimaryKey(t => new { t.SenderId, t.ReceiverId });

        CreateTable(
            "dbo.Friends",
            c => new
                {
                    SenderId = c.String(nullable: false, maxLength: 128),
                    ReceiverId = c.String(nullable: false, maxLength: 128),
                })
            .PrimaryKey(t => new { t.SenderId, t.ReceiverId })
            .ForeignKey("dbo.AspNetUsers", t => t.SenderId)
            .ForeignKey("dbo.AspNetUsers", t => t.ReceiverId)
            .Index(t => t.SenderId)
            .Index(t => t.ReceiverId);

    }

我该怎么办:(我在互联网上搜索过这似乎是合法的,但它不起作用

But when I add-migration, it creates 2 tables like this, and neither of them is what I need (one doesn't have foreign keys, one doesn't have Status properties)

这是因为您混合了 EF 支持的两种可能的 many-to-many 关联 - 一种使用隐式连接 table(来自 Fluent API 配置),另一种使用显式连接 table(Friend 实体)和两个 one-to-many 关联。

由于第一种方法只有在您没有与关联关联的其他数据时才能使用,而您有一个 (Status 属性),因此您需要使用第二种方法.

为此,请按如下方式更改导航属性的类型:

public class ApplicationUser : IdentityUser
{
    // ...
    public ICollection<Friend> Senders { get; set; }
    public ICollection<Friend> Receivers { get; set; }
}

和配置:

modelBuilder.Entity<ApplicationUser>()
    .HasMany(e => e.Senders)
    .WithRequired()
    .HasForeignKey(e => e.ReceiverId);

modelBuilder.Entity<ApplicationUser>()
    .HasMany(e => e.Receivers)
    .WithRequired()
    .HasForeignKey(e => e.SenderId);