InverseProperty Attribute in Entity Framework

InverseProperty Attribute in Entity Framework

In this article, I am going to discuss InverseProperty Data Annotation Attribute in Entity Framework Code First Approach with Examples. Please read our previous article where we discussed Index Attributes in Entity Framework Code First Approach with Examples.

InverseProperty Attribute in Entity Framework

The InverseProperty Attribute in Entity Framework Code First Approach is used when two entities have more than one relationship. A relationship in Entity Framework always has two endpoints. Each end must return a navigational property that maps to the other end of the relationship.

So, the point that you need to remember is InverseProperty Attribute informs the Entity Framework, which navigational property it relates to on the other end of the relationship. The default convention in Entity Framework correctly identifies only if there is a single relationship between two entities. But in the case of multiple relationships between two entities, it fails to correctly identify them. In such cases, we use the InverseProperty to help the Entity Framework correctly identify the relationship. If this is not clear at the moment, then don’t worry, we will try to understand this with an example.

Let us understand InverseProperty Attribute 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 EFCodeFirstDemo
{
    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 then copy and paste the following code into it. 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.

using System.Collections.Generic;
namespace EFCodeFirstDemo
{
    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 and this is possible because of the Navigation Property as shown in the below image. So, each entity must have a navigation property that maps to the navigation property of another entity.

InverseProperty Attribute in Entity Framework

As we are going to update the Entity Models many times, in order to avoid the Run-Time Exception when the model changes and when we rerun the application, let us set the database initializer as DropCreateDatabaseIfModelChanges. So, modify the context class as follows:

using System.Data.Entity;
namespace EFCodeFirstDemo
{
    public class EFCodeFirstContext : DbContext
    {
        public EFCodeFirstContext() : base("name=MyConnectionString")
        {
            //Setting the Database Initializer as DropCreateDatabaseIfModelChanges
            Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EFCodeFirstContext>());
        }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        }
        public DbSet<Teacher> Teachers { get; set; }
        public DbSet<Course> Courses { get; set; }
    }
}

Please make sure to have the connection string with the name MyConnectionString within the app.config file or web.config file as shown in the below image.

InverseProperty Data Annotation Attribute in Entity Framework Code First Approach with Examples

Now, modify the Main method of the Program class as follows. Here, we are adding a course entity to the database.

using System;
namespace EFCodeFirstDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            using (EFCodeFirstContext context = new EFCodeFirstContext())
            {
                var course = new Course() { CourseName = ".NET", Description = "C#.NET"};
                context.Courses.Add(course);
                context.SaveChanges();
                Console.WriteLine("Course Added");
                Console.ReadKey();
            }
        }
    }
}

With the above changes in place, now run the application. In our example, the Course and Teacher entities have a one-to-many relationship where one teacher can teach many different online courses and one course can be taught by a single teacher. As per the default conventions of Entity Framework, the above example would create the following tables in the database.

InverseProperty Attribute in Entity Framework Code First Approach with Examples

Now, suppose our requirement is to add another one-to-many relationship between the Teacher and Course Entities. For example, apart from OnlineTeacher, now we need to add OfflineTeacher. Let us first modify the Teacher class as follows to include the OfflineCourses collection Navigation Property.

using System.Collections.Generic;
namespace EFCodeFirstDemo
{
    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 EFCodeFirstDemo
{
    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 are having only one relationship between two entities, then it works fine. But when we have more than one relationship between two entities then we will not get the output as expected. With the above changes in place, now run the application and observe that the Entity Framework API creates the following Courses table with four foreign keys.

InverseProperty Attribute in Entity Framework Code First Approach

As you can see, we are having four Foreign Keys which should not be there. We should have two Foreign Keys pointing to the same TeacherId column of the Teacher table. To do this, we have to use the InverseProperty Attribute. 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 is taking 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.

InverseProperty Class in Entity Framework

Let us modify the Teacher Entity class as follows to use the InverseProperty Attribute as follows. 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.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace EFCodeFirstDemo
{
    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.

InverseProperty Attribute in Entity Framework Code First Approach

With the above changes in place, now Entity Framework API will able to identify the corresponding foreign key names. In this case, Entity Framework API will create foreign keys OnlineTeacher_TeacherId and OfflineTeacher_TeacherId when you run the application code as shown in the below image.

InverseProperty Attribute in Entity Framework

You can also use the [ForeignKey] Data Annotation Attribute to configure the foreign key name in the Course Entity as follows.

using System;
using System.ComponentModel.DataAnnotations.Schema;
namespace EFCodeFirstDemo
{
    public class Course
    {
        public int CourseId { get; set; }
        public string CourseName { get; set; }
        public string Description { get; set; }

        [ForeignKey("OnlineTeacher")]
        public Nullable<int> OnlineTeacherId { get; set; }
        public Teacher OnlineTeacher { get; set; }

        [ForeignKey("OfflineTeacher")]
        public int? OfflineTeacherId { get; set; }
        public Teacher OfflineTeacher { get; set; }
    }
}

With the above changes in place, run the application and this time it will create the Foreign Key columns based on the Foreign Key Attribute names as shown in the below image.

InverseProperty Attribute in Entity Framework with Examples

In the next article, I am going to discuss NotMapped Attribute in Entity Framework Code First Approach with Examples. Here, in this article, I try to explain InverseProperty Data Annotation Attribute in Entity Framework Code First Approach with Examples. I hope you enjoyed this InverseProperty Attribute in Entity Framework Code First Approach with Examples article. Please give your valuable feedback and suggestions about this article.

Leave a Reply

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