In Technologies
12
51 views

Do you know that when you have more than one foreign key relation with the same table then you write Inverse Property just above the Navigation Property? Ok, now this might be quite a direct approach to my blog post. Hence, in order to make it sound somewhat light, let’s first take a revision of the basics…

What Is Navigation Property?

This is the first question that arises after going through the very line of the article. So, let’s dig more into its details!

Navigation properties offer a smooth way to navigate an association between the two entity types. It further allows one to navigate and manage relationships in both of the directions, returning either a reference object (if the multiplicity is either one or zero-or-one) or a collection (if the multiplicity is many).

Entity Framework has an option to make only one navigation property for that you will need to define navigation relation in one class only not in both.

Navigation properties are Entity Frameworks way of representing Foreign Key relationships inside the database. Navigation properties allow you to define relationships between entities (rows in your database) in a way that makes sense in an object-oriented language. Consider the following database:

We would model dummy structure with something like the following:

public class Employee{

public Guid EmpId{ get; set; }

public string EmpName{get;set;}

}

public class Department{

public Guid DeptId{get;set;}

public Guid DEmpId{get;set;}

public string DeptName{get;set;}

public Employee Employees { get; set; }        //one way navigation property.

}

Which means we can use it in code like this:

String.Format(“{0} Departmentwise EmployeeName”, Department.Employees.EmpName)

How Does Navigation Property Works?

Defining navigation property means we are requesting Entity framework to join the Employee and Department tables.

For example :

  • context.Department.ToList(); //To get all the employees from table.
  • context.Department.Find(x=>x.Employees.EmpId==Id); //To find a particular department according to the mentioned Employee Id.

This will be translated into SQL like:

select e.empid, e.empname, d.deptid, d.deptName from employees as e inner join department d on e.Empid = d.DEmpid where EmpId = Id; 

How Does Entity Framework Detect Navigation Properties?

When entity framework examines a class which is attached to the context it finds other complex type properties on the class and assumes that they are a foreign key to that table. Entity framework then creates a foreign key with the name [PropertyName]_[PropertyIdName] for example in the case of the post class the Author is [PropertyName] and in the user table Id is the Id. This means Author_Id is generated as the foreign key name.The rules around navigation properties what’s acceptable and how they are generated are defined by a set of conventions.

I’m not going to go into any more detail on how these work but for more information, you can take a look at the following pages:

  • EF Feature CTP5: Pluggable Conventions
  • MSDN – System.Data.Entity.ModelConfiguration.Conventions Namespace
  • Entity Framework Navigation Property generation rules

Foreign Key Attribute

public class Student

{

public int StudentID { get; set; }

public string StudentName { get; set; } //Foreign key for Standard

public int StandardId { get; set; }

public Standard Standard { get; set; }

}

 

public class Standard {

public int StandardId { get; set; }

public string StandardName { get; set; }

public ICollection<Student> Students { get; set; }

}

As you can see in the above code, Student class includes foreign key StandardId, which is key property in Standard class.  So now, Code First will create StandardId column in Students class as shown below.

ForeignKey is overriding this. You can have a different name of a foreign key property name than the primary key of the second class.

public class Student

{

public int StudentID { get; set; }

public string StudentName { get; set; } //Foreign key for Standard

public int StandardRefId { get; set; }

[ForeignKey(“StandardRefId”)]

public Standard Standard { get; set; }

}

 

 

public class Standard

{

public int StandardId { get; set; }

public string StandardName { get; set; }

public ICollection<Student> Students { get; set; }

}

 

As seen in the above example, Student class has StandardRefId foreign key property name instead of StandardId. We defined it using the Foreign Key attribute on Standard navigation property so that Entity Framework’s Code-First can consider StandardRefId as it is foreign key, see below:

 

 

It’s not necessary to define the foreign key attribute to navigation property only but we can also put it in the normal properties of class as well. See below:

 

public class Student
{
public Student()
{ 
}
public int StudentID { get; set; }
public string StudentName { get; set; }
//Foreign key for Standard

[ForeignKey("Standard")]
public int StandardRefId { get; set; }
public Standard Standard { get; set; }
}
public class Standard
{
public Standard()
{ 
}
public int StandardId { get; set; }
public string StandardName { get; set; }
public ICollection<Student> Students { get; set; }
}

Inverse Property

The InverseProperty attribute is used when you have multiple relationships between classes.

Suppose this example:

 

public class Emploee{

public Guid EmpId{get;set;}

public string name{get;set}

}

 

public class DailyReports

{

public Guid DailyReportId{get;set;}

public Guid EmployeeId{get;set;}

public Guid AuthorisedBy{get;set;}

public string CreatedBy{get;set;}

 

//Navigation Properties..

public virtual Employee DailyEmpId{get;set;} //same table i.e Employee table.

public virtual Employee DailyAuthorisedBy{get;set;} //same table i.e Employee table.

public virtual Employee DailyCreatedBy{get;set;} //same table i.e Employee table.

}

 

Now here we will need Inverse Property because we have called EmployeeId thrice from the same table i.e Employee Table.

 

public class DailyReports

{

public Guid DailyReportId{get;set;}

[ForeignKey(“DEmpId”)]

public Guid EmployeeId{get;set;}

[ForeignKey(“DAuthEmpId”)]

public Guid AuthorisedBy{get;set;}

[ForeignKey(“DCreateEmpId”)]

public string CreatedBy{get;set;}

 

//Navigation Properties..

[InverseProperty(“DEmpId”)]

public virtual Employee DailyEmpId{get;set;} //same table i.e Employee table.

[InverseProperty(“DAuthEmpId”)]

public virtual Employee DailyAuthorisedBy{get;set;} //same table i.e Employee table.

[InverseProperty(“DCreateEmpId”)]

public virtual Employee DailyCreatedBy{get;set;} //same table i.e Employee table.

}

 

Consider another example:

 

public class Student
{
public Student()
{ 
}
public int StudentID { get; set; }
public string StudentName { get; set; }
public Standard CurrentStandard { get; set; }
public Standard PreviousStandard { get; set; }
}
public class Standard
{
public Standard()
{ 
}
public int StandardId { get; set; }
public string StandardName { get; set; }
public ICollection<Student> CurrentStudents { get; set; }
public ICollection<Student> PreviousStudents { get; set; }
}

As you can see in the above example, Student class includes two navigation properties to the Standard class. The same way Standard class includes two collection navigation properties for Student. Code-First creates four columns for this relationship, as shown below.

Inverse Property overrides this convention and specifies the alignment of the properties. The following example uses Inverse Property in Standard class to fix this problem.

public class Student
{
public Student()
{ 
}
public int StudentID { get; set; }
public string StudentName { get; set; }
public Standard CurrentStandard { get; set; }
public Standard PreviousStandard { get; set; }
}
public class Standard
{
public Standard()
{ 
}
public int StandardId { get; set; }
public string StandardName { get; set; }
[InverseProperty("CurrentStandard")]
public ICollection<Student> CurrentStudents { get; set; }
[InverseProperty("PreviousStandard")]
public ICollection<Student> PreviousStudents { get; set; }
}
As you can see in the above example, we have applied the Inverse Property attribute to CurrentStudents & PreviousStudents property and specify which reference property of Student class it belongs to. Now, Code-First will create only two foreign key column in Student table as shown below.

 

You can also use the Foreign Key attribute to include foreign key property with a different name as shown below:

 

public class Student
{
public Student()
{}
public int StudentID { get; set; }
public string StudentName { get; set; }
public int CurrentStandardId { get; set; }
public int PreviousStandardId { get; set; }
[ForeignKey("CurrentStandardId")]
public Standard CurrentStandard { get; set; }
[ForeignKey("PreviousStandardId")]
public Standard PreviousStandard { get; set; }
}
public class Standard
{
public Standard()
{
}
public int StandardId { get; set; }
public string StandardName { get; set; }
[InverseProperty("CurrentStandard")]
public ICollection<Student> CurrentStudents { get; set; }
[InverseProperty("PreviousStandard")]
public ICollection<Student> PreviousStudents { get; set; }
}

Concluding Words…

I hope I am able to explain the usage of Inverse Property and Foreign Key attribute for multiple relationships
between the same classes in detail. Stay tuned for more such informative updates!

Recent Posts
  • Ujjwal Parihar

    Amazing Bimmy Sharma,
    It’s a very informative type Technical Blog, that you have written. I hope, this blog will surly helps to experienced guys. All the Best !!!
    Post your next blog soon.

    • Bimmy Paneru

      Sure..

  • Ujjwal Parihar

    Keep it up.!!!

    • Bimmy Paneru

      Thanks!!

  • Vikas Dhama

    Great Work Bimmy!

    • Bimmy Paneru

      Thanks..

  • Tushar Goyal

    Good one!!! It will help to many people.

    • Bimmy Sharma

      Thanks

  • Rakesh

    Great! Thanks..

  • B Uma Sankar

    Definitely come in handy for me in near future, Thanks for the Blog Bimmy.

  • This blog is highly informative stating point to point info about foreign key in Entity Framework

  • Vinay Kumar

    Informative one. Keep Sharing More!

We Are Here to Help!
Name:
Phone:
Email:
Country:
Message:
Captcha:
 

Start typing and press Enter to search