为什么 Entity Framework 总是在迁移时创建一个额外的外键列?

Why does Entity Framework always create an additional foreign key column on migration?

我将从代码开始。创建了这两个实体:

    public class Product
    {
        [Key]
        public int Id { get; set; }
        public string ProductName { get; set; }

        public virtual ICollection<RelatedProduct> RelatedProducts { get; set; }        
    }

    public class RelatedProduct
    {
        [Key, Column(Order=0), ForeignKey("Product")]
        public int ProductId { get; set; }
        [Key, Column(Order = 1), ForeignKey("RelatedProduct")]
        public int RelatedProductId { get; set; }

        public virtual Product Product { get; set; }
        public virtual Product RelatedProduct { get; set; }
    }

然后当我 运行 add-migration 时,它产生了这个输出:

        CreateTable(
            "dbo.Product",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    ProductName = c.String(),
                })
            .PrimaryKey(t => t.Id);

        CreateTable(
            "dbo.RelatedProduct",
            c => new
                {
                    ProductId = c.Int(nullable: false),
                    RelatedProductId = c.Int(nullable: false),
                    Product_Id = c.Int(),
                })
            .PrimaryKey(t => new { t.ProductId, t.RelatedProductId })
            .ForeignKey("dbo.Products", t => t.ProductId, cascadeDelete: true)
            .ForeignKey("dbo.Products", t => t.RelatedProductId, cascadeDelete: true)
            .ForeignKey("dbo.Product", t => t.Product_Id)
            .Index(t => t.ProductId)
            .Index(t => t.RelatedProductId)
            .Index(t => t.Product_Id);

为什么会有第 3 列 Product_Id

我预计只有 2 列

您应该将 RelatedProduct 的第二个集合添加到 Product class 声明中,并用 InversePropertyAttribute 注释它们。由于您有两个 FK,因此您还应该有两个集合以进行适当的映射,否则会出现第三个 Product_Id FK 之类的副作用:

public class Product
{
    [Key]
    public int Id { get; set; }
    public string ProductName { get; set; }

    [InverseProperty("RelatedProduct")]
    public virtual ICollection<RelatedProduct> RelatedProducts { get; set; }        
    [InverseProperty("Product")]
    public virtual ICollection<RelatedProduct> Products { get; set; }        
}