The InverseProperty
informs the EF Core, which navigational property it relates to on the other end of the relationship. The default convention in EF Core correctly identifies only if there is a single relation between two entities. But in the case of multiple relationships, it fails to correctly identify them. In such cases, we use the InverseProperty
to help the EF core correctly identify the relationship.
Table of Contents
InverseProperty
A relationship in the Entity Framework Core always has two endpoints. Each end must return a navigational property that maps to the other end of the relationship. you can read about it from the tutorial Relationships in Entity Framework Core. The Entity Framework by convention detects this relationship and creates the appropriate Foreign Key column.
Consider the following model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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; } } |
In the above example, we have employee belonging to a particular department. The default convention automatically detects the relationship and creates the DepartmentID
foreign key column in the Employee table.
Multiple Relations
The employee and department is a single relationship. What if the employee belongs to multiple departments ?. Let us take the example of flight & airports. Flight departing from one airport and arrives at another. So the flight has multiple relationships with the Airport
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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; } } |
The DepartngFlights
property must map to DepartureAirport
property in the airport model and ArrivingFlights
property must map to ArrivalAirport property
.
The EF Core, throws the following error, when we run the migrations
Unable to determine the relationship represented by navigation `Airport.DepartingFlights’ of type ‘ICollection’. Either manually configure the relationship, or ignore this property using the ‘[NotMapped]’ attribute or by using ‘EntityTypeBuilder.Ignore’ in ‘OnModelCreating’.
Using InverseProperty
We solve this problem by using the InverseProperty
attribute on any one side of the relationships. Apply InverseProperty
attribute on that property. Specify the corresponding navigational property of the other end of the relationship as its argument.
The Airport class after applying the InverseProperty
is as shown below.
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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; } } |
Now the EF Core identifies the relationship correctly and creates only two fields as shown in the image below.
You can apply InverseProperty
on the Flight instead of the airport as shown below. Both will result in the same output
1 2 3 4 5 6 7 8 9 10 11 | 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; } } |