InverseProperty Attribute in Entity Framework Core

InverseProperty Attribute in Entity Framework Core

In this article, I will discuss the InverseProperty Data Annotation Attribute in Entity Framework Core (EF Core) with Examples. Please read our previous article discussing Index Attributes in Entity Framework Core with Examples.

InverseProperty Attribute in Entity Framework Core

In Entity Framework Core (EF Core), the InverseProperty attribute is used to specify the inverse navigation property of a relationship when the conventional naming and structure don’t provide enough information for EF Core to determine which properties are paired in a navigation relationship correctly.

This attribute is especially useful in situations where:

  • There are multiple relationships (multiple navigation properties) between two entities.
  • The property names do not follow conventions that allow EF Core to determine the relationships automatically.
Example to Understand 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.

The InverseProperty Attribute informs the EF Core, which navigational property relates to the other end of the relationship. The default convention in Entity Framework Core correctly identifies only if a single relationship exists between two entities. However, in the case of multiple relationships between two entities, it fails to identify them correctly. In such cases, we must use the InverseProperty Attribute to help the EF Core correctly identify the relationship. If this is unclear 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 will create two Entities, i.e., Course and Teacher. In our example, the Teacher Entity will be the Principal Entity, and the Course Entity will be the Dependent Entity. We will create the Foreign Keys inside the Dependent Entity to establish the relationships.

Create a class file named Course.cs, then copy and paste the following code. Here, we have created the following class with CourseId, CourseName, and Description properties along with the Teacher Reference Navigation Property, which makes the relationship 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 named Teacher.cs and copy and paste the following code. Here, we have created the following class with TeacherId and Name properties and 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; }
    }
}

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.

InverseProperty Attribute in Entity Framework Core

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 using Package Manager Console or .NET Core CLI.

So, open the Package Manager Console and Execute the add-migration and update-database commands as follows. 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.

InverseProperty in Entity Framework Core

In our example, the Course and Teacher entities have a one-to-many relationship where one teacher can teach many 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.

InverseProperty in EF Core

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, 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. An online teacher or an offline teacher can teach a Course. 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, it works fine. But when we have more than one relationship between two entities, EF Core throws an exception while executing the add-migration

With the above changes, open the 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.

InverseProperty in EF Core with Examples

How to Overcome this Problem in EF Core?

To overcome this problem, we must use the InverseProperty Attribute in EF Core. If you go to the definition of InverseProperty class, you will see the following. As you can see, the InverseProperty class has one constructor, which takes a string property parameter and 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.

InverseProperty Data Annotation Attribute in EF Core with Examples

Let us modify the Teacher Entity class as follows to use the InverseProperty Attribute. As you can see in the code below, we have decorated the InverseProperty Attribute with the OnlineCourses and OfflineCourses property and also specified the Course Entity Navigation property, which should point 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, 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.

InverseProperty Data Annotation Attribute in EF Core with Examples

With the above changes, open the Package Manager Console and Execute the add-migration and update-database commands as follows. 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.

InverseProperty Data Annotation Attribute in Entity Framework Core with Examples

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.

InverseProperty Data Annotation Attribute in Entity Framework Core with Examples

Advantages and Disadvantages of InverseProperty Attribute in EF Core:
Advantages:
  • Clarity: Provides an explicit way to denote the relationships between navigation properties, making the model clearer.
  • Flexibility: Allows for deviation from naming conventions without losing the intended relationships.
Disadvantages:
  • Verbosity: It can add additional annotations to the model, making it slightly more verbose.
  • Maintenance: When refactoring or renaming properties, developers need to remember to update the InverseProperty attribute values accordingly.

So, the InverseProperty attribute is a useful tool for explicitly specifying relationships in EF Core when conventions are insufficient or ambiguous. It helps ensure that the framework correctly interprets the relationships.

In the next article, I will discuss NotMapped Attribute in Entity Framework Core with Examples. Here, in this article, I try to explain the InverseProperty Data Annotation Attribute in Entity Framework Core with Examples. I hope you enjoyed this InverseProperty Attribute in EF Core with Examples article.

Leave a Reply

Your email address will not be published. Required fields are marked *