为一对多关系生成意外的外键

时间:2016-04-19 17:04:20

标签: c# .net entity-framework ef-migrations ef-fluent-api

我已经宣布了两个类 - Person和Vehicle,如下所示

public class Person
{
    public Person()
    {
        this.Vehicles = new HashSet<Vehicle>();
    }

    [Key]
    public int PersonID { get; set; }

    [Required, MaxLength(50)]
    public string FirstName { get; set; }

    [Required, MaxLength(50)]
    public string MiddleName { get; set; }

    [Required, MaxLength(50)]
    public string LastName { get; set; }

    [Required, MaxLength(10)]
    public string MobileNo1 { get; set; }
    [MaxLength(10)]
    public string MobileNo2 { get; set; }

    [MaxLength(50)]
    public string Email1 { get; set; }
    [MaxLength(50)]
    public string Email2 { get; set; }

    public virtual ICollection<Vehicle> Vehicles { get; set; }
}

public class Vehicle
{
    [Key]
    public int VehicleID { get; set; }

    [MaxLength(20)]
    public string VehicleNumber { get; set; }

    [ForeignKey("VehicleOwner")]
    public int? VehicleOwnerID { get; set; }
    [ForeignKey("VehicleOwnerID")]
    public virtual Person VehicleOwner { get; set; }

    [ForeignKey("VehicleDriver")]
    public int? VehicleDriverID { get; set; }
    [ForeignKey("VehicleDriverID")]
    public virtual Person VehicleDriver { get; set; }

    [ForeignKey("Person")]
    public int? PersonID { get; set; }
    [ForeignKey("PersonID")]
    public virtual Person Person { get; set; }

}

这会在车辆表上生成两个外键

.ForeignKey("dbo.Person", t => t.PersonID)
.ForeignKey("dbo.Person", t => t.Person_PersonID)

而我所期望的只是

.ForeignKey("dbo.Person", t => t.PersonID)

最初我认为这可能是因为我错过了将实体声明为虚拟但事实并非如此。我无法通过此代码检测到问题。

与“车辆”一样,我有另一个类 - 文档与Person的结构和关系有些相同。但是对于Documents,外键是按预期生成的。

2 个答案:

答案 0 :(得分:1)

你有3个类指向Person,所以配置为:

public class Vehicle
{
    [Key]
    public int VehicleID { get; set; }

    [MaxLength(20)]
    public string VehicleNumber { get; set; }

    public int? VehicleOwnerID { get; set; }
    [ForeignKey("VehicleOwnerID")]
    public virtual Person VehicleOwner { get; set; }

    public int? VehicleDriverID { get; set; }
    [ForeignKey("VehicleDriverID")]
    public virtual Person VehicleDriver { get; set; }

    public int? PersonID { get; set; }
    [ForeignKey("PersonID")]
    public virtual Person Person { get; set; }

}

虽然这是不正确的语法,但第二个外键来自人员上的车辆集合,EF无法解析它所属的FK。

因此,在您的集合的Person类中,您需要指向车辆中的相应导航:

[InverseProperty("Person")]
public virtual ICollection<Vehicle> Vehicles { get; set; }

http://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-code-first.aspx

答案 1 :(得分:0)

正如史蒂夫所说,这是因为你引用了车辆类中的人物。因此,Entity Framework为Person,VehicleOwner和VehicleDriver创建了一个密钥。然而,由于人员收集车辆,它创造了另一个关键。您必须在此处使用inverse属性来告诉Entity Framework您要在实际的Vehicle.Person属性上构建Vehicle和Person之间的关系。你可以通过

来做到这一点
[InverseProperty("Person")]
public virtual ICollection<Vehicle> Vehicles { get; set; }

另外,你是多余的:

[ForeignKey("Person")]
public int? PersonID { get; set; }
[ForeignKey("PersonID")]
public virtual Person Person { get; set; }

从int中删除ForeignKey?您的Vehicle类中的PersonID。