InverseProperty
通知 EF Core,它在关系的另一端与哪个导航属性相关。 EF Core中的默认约定仅在两个实体之间存在单一关系时才能正确识别。 但在多重关系的情况下,它无法正确识别它们。 在这种情况下,我们使用 InverseProperty
来帮助 EF 核心正确识别关系。
InverseProperty
Entity Framework Core 中的关系始终有两个端点。 每一端都必须返回一个映射到关系另一端的导航属性。 您可以从 Entity Framework Core 中的关系教程中了解它。 实体框架按照惯例检测这种关系并创建适当的外键列。
考虑以下模型
public class Employee
{
public int EmployeeID { get; set; }
public string Name { get; set; }
public int DepartmentID { get; set; }
public Department Department { get; set; }
}
public class Department
{
public int DepartmentID { get; set; }
public string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
在上面的示例中,我们有属于特定部门的员工。 默认约定会自动检测关系并在 Employee
表中创建 DepartmentID
外键列。
多重关系
员工和部门是单一关系。 如果员工属于多个部门怎么办? 让我们以航班和机场为例。 从一个机场起飞并到达另一个机场的航班。 所以航班与机场有多重关系
public class Flight
{
public int FlightID { get; set; }
public string Name { get; set; }
public Airport DepartureAirport { get; set; }
public Airport ArrivalAirport { get; set; }
}
public class Airport
{
public int AirportID { get; set; }
public string Name { get; set; }
public virtual ICollection<Flight> DepartingFlights { get; set; }
public virtual ICollection<Flight> ArrivingFlights { get; set; }
}
DepartngFlights
属性必须映射到机场模型中的 DepartureAirport
属性,而 ArrivingFlights
属性必须映射到 ArrivalAirport
属性。
当我们运行迁移时,EF Core 抛出以下错误
无法确定由类型为“ICollection
”的导航“Airport.DepartingFlights
”表示的关系。 手动配置关系,或使用“[NotMapped]
”属性或使用“OnModelCreating
”中的“EntityTypeBuilder.Ignore
”忽略此属性。
使用InverseProperty
我们通过在关系的任何一侧使用 InverseProperty
属性来解决这个问题。 在该属性上应用 InverseProperty
属性。 指定关系另一端的相应导航属性作为其参数。
应用 InverseProperty
后的 Airport
类如下所示。
public class Airport
{
public int AirportID { get; set; }
public string Name { get; set; }
[InverseProperty("DepartureAirport")]
public virtual ICollection<Flight> DepartingFlights { get; set; }
[InverseProperty("ArrivalAirport")]
public virtual ICollection<Flight> ArrivingFlights { get; set; }
}
现在 EF Core 正确识别关系并仅创建两个字段,如下图所示。
您可以在航班而不是机场上应用 InverseProperty
,如下所示。 两者都会产生相同的输出
public class Flight
{
public int FlightID { get; set; }
public string Name { get; set; }
[InverseProperty("DepartingFlights")]
public Airport DepartureAirport { get; set; }
[InverseProperty("ArrivingFlights")]
public Airport ArrivalAirport { get; set; }
}