Navigation Property With Code First (Navigation Property In EF)

What is Navigation Property?

It is a way to represent a foreign key relationship in the database or define the relationship between the two entities.

Example

Client - Client ID, Name.

Project - Project ID, Client ID.

It means the project is linked with the client on the basis of Client ID.

Relationship: Project HAS-a client.

If we model this relationship, it would look like as shown below:

  1. class Client  
  2. {  
  3.    public string Name {getset}  
  4. }   
  5.   
  6. cass Project  
  7. {   
  8.    public Client objClient {getset}  
  9. }  
It means we can do this in the following manner:

Project.objClient.Name;

Now, if we want to achieve this structure in the database, we need to define our model in the way shown below:
  1. class Client  
  2.    
    public 
    int Id {getset ;}  
  3.    public string {getset ;}  
  4. }  
  5.  
  6. class Project   
  7. {  
  8.    public int Id {getset ;}  
  9.    public Client client {getset ;} // Project HAS-a client. Name of Field will be   
  10.    // [PropertyName]_[PropertyIDName] “client_Id”  
  11. }  
Note

Association between two entities defines three things: type of entity, type of association, and referential integrity.

How Navigation property works

When we apply navigation property in our code, it means we are asking EF to automatically perform a join between the two tables.

Example

Code accesses project info of the client name ASD, as shown below:
  1. Context.Projects.Where(p ->p.client.Name == ‘ASD’);  
Now, SQL translation of the code, given above is as follows:
  1. Select Projects .Id, Projects .client_Id  
  2. From Projects inner join Clients  
  3. On Projects.client_Id = Clients.Id  
  4. Where Clients.Name = ‘ASD’  
How and when navigation properties load

By default, navigation properties are null, they are not loaded by default.  For loading navigation property, we use “include” method of IQuearable and this type of loading is called Eager loading.

Eager loading: It is a process by which a query for one type of entity loads the related entities as a part of query and it is achieved by “include” method of IQuerable.

How Navigation properties loading works,
  1. class Client  
  2. {  
  3.    public int ID {get; set ;}  
  4.    public string Name {get; set ;}  
  5. }   
  6.   
  7. Class Project   
  8. {  
  9.    public int ID {get; set ;}  
  10.    public Client Clients {get; set ;} // Project HAS-a client. Name of Field will be   
  11.    [PropertyName]_[PropertyIDName] “Clients_ID”  
  12. }  
Clients 

IDName
1CMD
2NSH

Projects

IDClients_ID
1001
1011
  1. Get all the projects but do not get the linked clients.
    1. Context.Projects.ToArray()  
    2.   
    3.   
    4. <ArrayOfProject>  
    5.     <Project>  
    6.         <ID>100</ID>  
    7.         <Clients>null</Clients>  
    8.     </Project>  
    9.     <Project>  
    10.         <ID>101</ID>  
    11.         <Clients>null</Clients>  
    12.     </Project>  
    13. </ArrayOfProjects>  

  2. Filter, using where clause, which works perfectly and filters the records, but the linked property clients are not loaded.
    1. Context.Project.Where(p =>p.Clients.Name==”CMD”) .ToArray()  
    2.   
    3. <ArrayOfProject>  
    4.     <Project>  
    5.         <ID>100</ID>  
    6.         <Clients>null</Clients>  
    7.     </Project>  
    8. </ArrayOfProjects>  

  3. Include statement is able to fetch or load the linked item of an entity.
    1. Context.Project.include(p =>p.Clients).ToArray();  
    2.   
    3. <ArrayOfProject>  
    4.     <Project>  
    5.         <ID>100 </ID>  
    6.         <Client>  
    7.             <ID>1</ID>  
    8.             <Name> CMD</Name>  
    9.         </Client>  
    10.     </Project>  
    11.     <Project>  
    12.         <ID>101 </ID>  
    13.         <Client>  
    14.             <ID>1</ID>  
    15.             <Name> CMD</Name>  
    16.         </Client>  
    17.     </Project>  
    18. <ArrayOfProject>  

How Entity Framework detect Navigation properties

  1. Complex type

    When we define complex type inside class, which is attached with the context for Entity framework, consider this complex type as a foreign key inside this class. Hence, it creates Foreign key by name [PropertyName]_[PropertyIDName] (Name by which property is defined and the name of Primary key is of complex type.)

    Example
    1. class Client   
    2. {  
    3.    public int ClientId {getset;}  
    4.    public string ClientName {getset;}  
    5.   
    6. }  
    7.   
    8. Class Project  
    9. {  
    10.    public int ProjectId {getset;}  
    11.    public string ProjectName {getset;}  
    12.   
    13.    public Client ObjClient {getset;}  
    14. }  


    In the above example, we have two classes: Client and Project.

    Now, the client is defined inside the Project class. Hence, these two classes are attached with the context by dbset.Thus, entity frame considers it as a Foreign key.

    It will create a Foreign key inside the Project table by the following naming convention [PropertyName]_[PropertyIDName], which means, it will look like “ObjClient_ClientId”

  2. By Naming conventions

    When we define the complex type property inside a class and also add the property with the same name as a Primary key of complex type, the Entity Framework considers this and defines a property as a Foreign key of the table with the same name.

    Example
    1. class Client   
    2. {  
    3.    public int ClientId {getset;}  
    4.    public string ClientName {getset;}  
    5.   
    6. }  
    7.   
    8. class Project  
    9. {  
    10.    public int ProjectId {getset;}  
    11.    public string ProjectName {getset;}  
    12.   
    13.    public int ClientId {getset;} // Entity framework treat it as foreign key, and create same   
    14.    // name property as Foreign key into table.   
    15.    public Client ObjClient {getset;}  
    16. }  


    In the above example in Project table, the Entity framework creates Foreign key by the name “ClientId”.

Ways to define Foreign key in Entity Framework

  1. By adding complex type as a property,
    1. class Client   
    2. {  
    3.    public intClientId {getset;}  
    4.    public string ClientName {getset;}  
    5.   
    6. }  
    7.   
    8. class Project  
    9. {  
    10.    public intProjectId {getset;}  
    11.    public string ProjectName {getset;}  
    12.   
    13.    public Client ObjClient {getset;}
    14. }  
    Only add property of complex type, and it will automatically create “ObjClient_ClientId” foreign key into project table.

  2. By adding complex type as a property and adding the property by the same name and typing it as Primary key of a complex type,
    1. class Client   
    2. {  
    3.    public int ClientId {getset;}  
    4.    public string ClientName {getset;}  
    5.   
    6. }  
    7.   
    8. class Project  
    9. {  
    10.    public int ProjectId {getset;}  
    11.    public string ProjectName {getset;}  
    12.   
    13.    public int ClientId {getset;} // Entity framework treat it as foreign key, and create same   
    14.    // name property as Foreign key into table.   
    15.    public Client ObjClient {getset;}  
    16. }  

  3. By using data annotation Foreign key attribute,

    Data annotation Foreign key attribute can be used in the two ways -- one with the navigation property defined inside the class or with a Foreign key, defined inside the class.

    Example

    Foreign key attribute is used over a navigation property.
    1. class Project   
    2. {  
    3.    public int ProjectId {get;set;}  
    4.    public string ProjectName{getset;}  
    5.   
    6.    [ForeignKey("FkClientId")]  
    7.    public Client client {getset;} // Navigation property   
    8. }   



    Hence, at this stage, it will give an error, because here we have specified a Foreign key. Hence, EF will not create a default foreign key by [PropertyName]_[PropertyIdName]. Hence, EF tries to find Foreign key, specified by name “FkClientId”. It will give an error for not finding Foreign key by the FkClientId inside the Project class. Hence, we need to define Foreign key property.
    1. class Project   
    2. {  
    3.    public int ProjectId {get;set;}  
    4.    public string ProjectName{getset;}  
    5.    public int FkClientId {getset;} // It will become foreign key.   
    6.    [ForeignKey("FkClientId")]  
    7.    public Client client {getset;} // Navigation property   
    8. }   


    Example

    Foreign key attribute is used over the property with which you want to make Foreign key.
    1. class Project   
    2. {  
    3.    public int ProjectId {get;set;}  
    4.    public string ProjectName{getset;}  
    5.    [ForeignKey ("Client")]  
    6.    public int FkClient {getset;}   
    7. }   



    On this stage, the code given above will give an error, because in the code given above, we are saying tha, FkClient is a Foreign key of Client table, but EF will not create this foreign key due to the absence of the navigation property of Client, it means at least one navigation property of client should be there adding its key as a foreign key into the project.
    1. class Project   
    2. {  
    3.    public int ProjectId {get;set;}  
    4.    public string ProjectName{getset;}  
    5.    [ForeignKey ("Client")]  
    6.    public int FkClient {getset;}   
    7.    public Client Client{get;set;} // Navigation Property.  
    8. }   

  4. By using data annotation Foreign key attribute, we can give different name to Foreign key property.

Note

The first part of the expression defines the navigation property on the current entity, the second part of the expression defines the reverse navigation property.

What is Reverse Navigation property?

Here, we will discuss reverse navigation property.

Two navigation properties that we have defined on each end of a relationship are in fact different ends of the same relationship.

It has been able to do this because there has been only one possible match.

Type of Navigation properties,
  1. Optional relationship (Null able foreign key and multiplicity, 0...1)(One to one relationship )(Zero or one).
  2. Required relationship (One to many relationship).
  3. Many relationship (Many to Many relationship).

One-to-One Relationship

Optional relationship (Null able foreign key and multiplicity, 0...1)(One to one relationship )(Zero or one).

Primary key value table contains one record and its related table contains one or zero records related to this table. This relationship is called a one to one relationship.

Suppose, take an example of “Client” and “ClientAddress”, which has a one to one relationship (zero or one),this means the client can have one or zero addresses.

Hence, if we create a class of the client having ID and Name; create Class ClientAddress contains ID , Address and City.

For setting up one to one relationships between the Client and ClientAddress, we need to define the navigation property of the client into ClientAddress and specify a Foreign Key of client into ClientAddress and then define the reverse navigation property of ClientAddress into the client. In this way, EF handles One to One relationships.

  1. class Client  
  2. {  
  3.    public int ClientID{get;set;};  
  4.    public String Name{get;set;};   
  5. }   
  6. clientAddress  
  7. {  
  8.   
  9.    public int ClientAddressId {get;set;}  
  10.    public String Address {get;set;}  
  11.    public string City {get;set;}  
  12.    [ForeignKey ("Client")]  
  13.    public int FkClient {getset;}   
  14.    public Client Client{get;set;} // Navigation Property.
  15. }  
One-to-many relationships

Primary key value table contains one record and its related table contains one, zero or many records related to it. This relationship is called a One-to-Many relationship.

Example

Suppose we have “Client” and “Project” entity. 

One client can have multiple projects, but one project can only link with one project.

Note

Reverse navigation property of the expression is defined as a collection. In this case, there is a one-to-many relationship.
  1. class Client  
  2. {  
  3.    public int ClientID{get;set;}  
  4.    public String ClientName{get;set;}  
  5.    // Second Part of expression define reverse navigation property   
  6.    public virtual ICollection<Project> Projects { getset; }  
  7. }   
  8.   
  9.   
  10.   
  11. class Project  
  12. {  
  13.    public int ProjectID{get;set;}  
  14.    public String ProjName {get;set;}  
  15.    // First Part of expression define navigation property   
  16.    public Client Clients {get;set}  
  17. }   


Hence, in the code given above, you can see the client type contains a collection of Project type. Project type contains client type entity. 

These are the two ends of the expression of the navigation properties and it shows that the client can have a multiple project due to which, the project is defined in the collection inside the client.

On the other hand, project only links with the single client, due to which it contains the client type entity.

Many-to-Many relationship

One table records are able to relate with any numbers (or zero records) of records of the second, the second table records are able to relate with any number of records of the first table.

Many-to-many relationship require a third table, which is called linking or mapping the table.

Example: relationship between “Student” and “Course” entity,

One student can be enrolled for multiple courses and one course can be taught to many students.

Hence, in this case, a third table is required, which will contain Pk of both entities.
  1. class Student  
  2. {  
  3.    public int StudentId {get;set;}  
  4.    public String Name {get;set;}  
  5.    public String Address {getset; }   
  6.    public virtual ICollection<Course > Courses { getset; }  
  7.   
  8. }  
  9.   
  10. class Course   
  11. {  
  12.    public int CourseId {getset;}  
  13.    public String CourseName {get;set;}  
  14.    public virtual ICollection<Student>Students { getset; }  
  15. }  

Up Next
    Ebook Download
    View all
    Learn
    View all