Back to: ASP.NET Core Tutorials For Beginners and Professionals
InverseProperty Attribute in Entity Framework Core
In this article, I am going to discuss InverseProperty Data Annotation Attribute in Entity Framework Core (EF Core) with Examples. Please read our previous article, where we discussed Index Attributes in Entity Framework Core with Examples.
InverseProperty Attribute in Entity Framework Core
The InverseProperty Attribute in Entity Framework Core is used when two entities have more than one relationship. A relationship in EF Core has two endpoints. Each end must return a navigational property that maps to the other end of the relationship.
So, you need to remember that InverseProperty Attribute informs the EF Core, which navigational property it relates to on the other end of the relationship. The default convention in Entity Framework Core correctly identifies only if a single relationship exists between two entities. But in the case of multiple relationships between two entities, it fails to identify them correctly. In such cases, we need to use the InverseProperty Attribute to help the EF Core correctly identify the relationship. If this is not clear now, don’t worry; we will try to understand this with an example.
Let us understand InverseProperty Attribute in EF Core with one example. To understand this concept, we are going to create two Entities, i.e., Course and Teacher.
Create a class file with the name Course.cs and then copy and paste the following code into it. Here, you can see we have created the following class with CourseId, CourseName, and Description properties along with the Teacher Reference Navigation Property, which makes the relationship as One to One between the Course and Teacher.
namespace EFCoreCodeFirstDemo.Entities { public class Course { public int CourseId { get; set; } public string? CourseName { get; set; } public string? Description { get; set; } public Teacher? OnlineTeacher { get; set; } } }
Create a class file with the name Teacher.cs and copy and paste the following code. Here, you can see we have created the following class with TeacherId, and Name properties along with the Course Collection Navigation Property, which makes the relationship One-to-Many between the Teacher and Course.
namespace EFCoreCodeFirstDemo.Entities { public class Teacher { public int TeacherId { get; set; } public string? Name { get; set; } public ICollection<Course>? OnlineCourses { get; set; } } }
Now, the two entities have a one-to-many relationship, which is possible because of the Navigation Property, as shown in the image below. So, each entity must have a navigation property that maps to the navigation property of another entity.
Next, modify the context class as follows:
using Microsoft.EntityFrameworkCore; namespace EFCoreCodeFirstDemo.Entities { public class EFCoreDbContext : DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer(@"Server=LAPTOP-6P5NK25R\SQLSERVER2022DEV;Database=EFCoreDB;Trusted_Connection=True;TrustServerCertificate=True;"); } protected override void OnModelCreating(ModelBuilder modelBuilder) { } public DbSet<Course> Courses { get; set; } public DbSet<Teacher> Teachers { get; set; } } }
As we already discussed, whenever we add or update domain classes or configurations, we need to sync the database with the model using add-migration and update-database commands either using Package Manager Console or .NET Core CLI.
So, open Package Manager Console and Execute the following add-migration and update-database commands. You can give any name to your migration. Here, I am giving DBMigration1. The name that you are giving it should not be given earlier.
In our example, the Course and Teacher entities have a one-to-many relationship where one teacher can teach many different online courses, and a single teacher can teach one course. As per the default conventions of Entity Framework Core, the above example would create the following tables in the database.
Now, suppose our requirement is to add another one-to-many relationship between the Teacher and Course Entities. For example, apart from OnlineTeacher, we now need to add OfflineTeacher. First, Let us modify the Teacher class to include the OfflineCourses collection Navigation Property.
namespace EFCoreCodeFirstDemo.Entities { public class Teacher { public int TeacherId { get; set; } public string? Name { get; set; } public ICollection<Course>? OnlineCourses { get; set; } public ICollection<Course>? OfflineCourses { get; set; } } }
Next, modify the Course Entity as follows to include the OfflineTeacher Reference Navigational property.
namespace EFCoreCodeFirstDemo.Entities { public class Course { public int CourseId { get; set; } public string? CourseName { get; set; } public string? Description { get; set; } public Teacher? OnlineTeacher { get; set; } public Teacher? OfflineTeacher { get; set; } } }
Now, the Course and Teacher entities have two one-to-many relationships. A Course can be taught by an online teacher as well as an offline teacher. In the same way, a teacher can teach multiple online courses as well as multiple offline courses.
So, if we have only one relationship between two entities, then it works fine. But when we have more than one relationship between two entities, then EF Core throws an exception while executing the add-migration.
With the above changes, open Package Manager Console and Execute the add-migration command. And you should get the following error. It is clearly saying that it is unable to determine the relationship.
How to Overcome this Problem in EF Core?
In order to overcome this problem, we need to use the InverseProperty Attribute in EF Core. If you go to the definition of InverseProperty class, then you will see the following. As you can see, the InverseProperty class has one constructor, which takes a string property parameter as well as a read-only property to return the property name. This class specifies the inverse of a navigation property that represents the other end of the same relationship.
Let us modify the Teacher Entity class as follows to use the InverseProperty Attribute. As you can see in the below code, we have decorated the InverseProperty Attribute with the OnlineCourses and OfflineCourses property and also specified the Course Entity Navigation property, which should it points to make the relationship. With this, OnlineCourses will have a relationship with the OnlineTeacher property, and OfflineCourses will have a relationship with the OfflineTeacher property.
using System.ComponentModel.DataAnnotations.Schema; namespace EFCoreCodeFirstDemo.Entities { public class Teacher { public int TeacherId { get; set; } public string? Name { get; set; } [InverseProperty("OnlineTeacher")] public ICollection<Course>? OnlineCourses { get; set; } [InverseProperty("OfflineTeacher")] public ICollection<Course>? OfflineCourses { get; set; } } }
As you can see, now we have applied the [InverseProperty] attribute on two collection navigation properties, i.e., OnlineCourses and OfflineCourses, to specify their related navigation property in the Course entity. For a better understanding, please have a look at the below image.
With the above changes in place, open Package Manager Console and Execute the following add-migration and update-database commands. You can give any name to your migration. Here, I am giving DBMigration2. The name that you are giving it should not be given earlier.
Now, verify the database, and you should see the following. As you can see, in this case, Entity Framework Core creates foreign keys OnlineTeacherTeacherId and OfflineTeacherTeacherId.
In the next article, I am going to discuss NotMapped Attribute in Entity Framework Core with Examples. Here, in this article, I try to explain InverseProperty Data Annotation Attribute in Entity Framework Core with Examples. I hope you enjoyed this InverseProperty Attribute in EF Core with Examples article.