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

时间:2016-11-08 06:47:31

标签: 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
}

1 个答案:

答案 0 :(得分:15)

外键属性用于:

  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; }
    
  2. OR表示给定导航属性的外键属性的名称:

    // 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; }
    
  3. 当默认的EF代码优先约定不适用或以不适合您的方式应用时,它很有用。 Here您可以看到EF代码优先约定列表。

    当您需要指示类 A 中的导航属性与类 B 中的另一个导航属性相同的外键相关时,使用

    反向属性属性。例如:

    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; }   
    }
    

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

    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; }   
    }
    

    现在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; }
    }
    

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