实体框架中反向属性和外键之间有什么区别?

IAm*_*shL 13 c# entity-framework

我知道当你在类之间有多个关系时会使用Inverse属性.但我在反向属性和外键属性之间感到困惑,因为它们都用于定义关系.

public class PrivilegeToDbOperationTypeMap : BaseEntity
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity), Column(Order = 0)]
    public int PrivilegeToDbOperationTypeMapId { get; set; }

    [ForeignKey("privilegeLookup"), Column(Order = 1)]
    [Index("IX_PrivilegeLookupId_DbOperationLookupId", 1, IsUnique = true)]
    public int PrivilegeLookupId { get; set; }

    [ForeignKey("dbOperationTypeLookup"), Column(Order = 2)]
    [Index("IX_PrivilegeLookupId_DbOperationLookupId", 2, IsUnique = true)]
    public int DbOperationLookupId { get; set; }

    #region Navigation Properties

    public PrivilegeLookup privilegeLookup { get; set; }

    public DbOperationTypeLookup dbOperationTypeLookup { get; set; }

    [InverseProperty("privilegeToDbOperationTypeMap")]
    public ICollection<RoleToPrivilegeDbOperationTypeMap> roleToPrivilegeDbOperationTypeMaps { get; set; }

    #endregion Navigation Properties
}
Run Code Online (Sandbox Code Playgroud)

Evk*_*Evk 18

外键属性用于:

  1. 指示与给定外键属性相关的导航属性的名称

    // this is foreign key property with related "privilegeLookup" navigation property. Database column name will be PrivilegeLookupId
    [ForeignKey("privilegeLookup"), Column(Order = 1)]       
    public int PrivilegeLookupId { get; set; }
    // this is related navigation property
    public PrivilegeLookup privilegeLookup { get; set; }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 或指示给定导航属性的外键属性的名称:

    // this is foreign key property
    public int PrivilegeLookupId { get; set; }
    // this is navigation property with related foreign key property
    [ForeignKey("PrivilegeLookupId")]  
    public PrivilegeLookup privilegeLookup { get; set; }
    
    Run Code Online (Sandbox Code Playgroud)

当默认的EF代码优先约定不适用或以不适合您的方式应用时,它很有用.在这里,您可以看到EF代码优先约定列表.

当您需要指示A类中导航属性与B类中的另一个导航属性相同的外键时,将使用Inverse属性属性.例如:

public class Student
{
    public int StudentID { get; set; }

    public Standard CurrentStandard { get; set; }
    public Standard PreviousStandard { get; set; }
}

public class Standard
{    
    public int StandardId { get; set; }

    public ICollection<Student> CurrentStudents { get; set; }
    public ICollection<Student> PreviousStudents { get; set; }   
}
Run Code Online (Sandbox Code Playgroud)

这里我们有两个类,每个类都有两个导航属性.我们的目的是在表Student中有两个外键,可能名为CurrentStandardId和PreviousStandardId,类Standard的导航属性也与相同的外键(一对多关系)相关.但是,在这种情况下,如果没有进一步的指导,EF将无法实现这一点 - 相反,它将创建4个外键.为了引导它,我们必须使用inverse属性:

public class Standard
{
    public int StandardId { get; set; }

    // reference to the name of another navigation property in class Student
    [InverseProperty("CurrentStandard")]
    public ICollection<Student> CurrentStudents { get; set; }

    // reference to the name of another navigation property in class Student
    [InverseProperty("PreviousStandard")]
    public ICollection<Student> PreviousStudents { get; set; }   
}
Run Code Online (Sandbox Code Playgroud)

现在EF了解我们的意图并且只会创建两个外键,但名称不会很好.要更改列名,我们可以使用外键属性:

public class Student 
{
    public int StudentID { get; set; }

    public int CurrentStandardId { get; set; }
    public int PreviousStandardId { get; set; }

    [ForeignKey("CurrentStandardId")]
    public Standard CurrentStandard { get; set; }

    [ForeignKey("PreviousStandardId")]
    public Standard PreviousStandard { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

长话短说 - EF可以根据代码约定推断出很多东西.但是当它不能时(例如,当你在同一个类中有两个外键时) - 你必须使用你问题中的属性来帮助它.

  • 为了使其完整,属性`public ICollection&lt;Student&gt; CurrentStudents`也可以用`[ForeignKey("CurrentStandardId")]`注释。这使它看似接近于 `InverseProperty`,但它只能引用原始属性,而不是引用属性,例如 `CurrentStandard`。 (3认同)
  • 需要强调的是,仅当存在多个同一类型的导航属性时才需要 InverseProperty。如果 Student 仅具有 CurrentStandard,而 Standard 仅具有 CurrentStudents,则 EF 可以推断出正确的关系,而无需用 InverseProperty 表示。 (2认同)