In relational databases, it is a healthy practice to divide the data between related tables. For Example, the employee working in a particular department. We do not store both the information in the same table but divide them into Employee & Department table.
When we divide tables, we also need to specify the relationships between them. For example, if you are looking for an employee working in a particular department, then you need to specify the relationship between employees and the department table. The relationship between these tables is defined using the foreign keys. We then use these relationships to query the database to get the meaningful data.
Table of Contents
Definition of Terms
There are few terms you should be familiar with when discussing the relationships between entities
Consider the following model of Employee and Department
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Employee { public int EmployeeID { get; set; } public string Name { get; set; } public int DepartmentID { get; set; } public virtual Department Department { get; set; } } public class Department { public int DepartmentID { get; set; } public string Name { get; set; } public virtual ICollection<Employee> Employees { get; set; } } |
The entities participating in the relation can be either Principal entity or Dependent Entity
Principal Entity
The Department Model is the Principal entity (or parent) as Employee entity needs it. The Principal Entity can exist on its own. It will contain the primary/alternate key properties, which will be inserted into the Depdendent Entity
Dependent Entity
The Dependent Entity (or child) dependent on Principal Entity. The Employee Entity is the Dependent Entity here as it needs Department Entity. The Dependent Entity contains the foreign key property.
Foreign key
The Foreign Key is the glue between Principal Entity and its Dependent Entity. It is stored in the Dependent Entity and points to the Parent Entity. In the above example, DepartmentID is the Foreign Key in the Dependent Entity, which links
Principal Key
The Principal Key is the property that uniquely identifies the Principal Entity and participates in the relationship. The Principal Key can be either primary key or an alternate key. The DepartmentID in the Department Entity is the Principal Key
A Navigation Property is a property that defined on the principal and/or dependent entity that contains a reference to the related entity
Navigation properties describe the relationship between two entity types. They allow us to navigate from one end of the relationship to the other end. A relationship in the Entity Framework always has two endpoints. Each endpoint, which participates in the relationship must return a navigation property describing the relationship.
For Example Consider the Employee & Department model.
In the above example, the Department Property in the Employee class (
dependent entity) holds the reference to the Department Class (Principal entity) is one end of the relationship. The Employees Collection in Department class is part of the other end of the relationship.
There are two types of navigation properties that can be returned by the entity types depending on the type of relationship they participate.
- Reference Object (If the relationship is one or Zero-or-One)
In the above example, the Department property in Employee class - Collection (If the relationship is Many)
The Employees Collection in the Department Class
Relationship types
The relationships can come in various types. For Example, Employee can belong to one department, but the department can have many employees. An Employee can be part of many projects and projects can have many employees working under it.
There are three specific types of relationships can exists between tables
- One to One
- One to Many
- Many to Many
One to One relationship
The Relationship between husband and wife is an example of one to one relationship. You can have only one spouse. One to one relationship usually does not happen in database design. Because you can combine them into one table easily without breaking any rule.
For our example, consider the domain class Employee and EmployeeAddress. Let us assume that employee can have only one address. This will create a one to one relationship between employee and EmployeeAddress table. In a One to one relationship PrimaryKey of one table (employeeID of employee table) is both Primary key and Foreign key in the second table (EmployeeAddress). Hence our entity classes will be as shown below
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Employee { public int EmployeeID { get; set; } public string Name { get; set; } //Navigation property Returns the Employee Address public virtual EmployeeAddress EmployeeAddress { get; set; } } public class EmployeeAddress { [Key, ForeignKey("Employee")] public int EmployeeID { get; set; } public string Address { get; set; } //Navigation property Returns the Employee object public virtual Employee Employee { get; set; } } |
Note that we have created the navigational property which returns the reference to the related entity. In Employee class navigational property returns the reference to the EmployeeAddress object. In EmployeeAddress class navigational property returns the reference to the Employee object.
Configure one to one relationship in Entity Framework Core
One to Many Relationship
The Relationship between mother and children is an example of one to Many relationships. A Mother can have many children, but a child can have only one mother.
The relationship between employee and the department is one to many. The employee belongs to only one department. The department can have many employees. In a One to Many relationship Primary key of the department table (DepartmentID) is defined as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class Employee { public int EmployeeID { get; set; } public string Name { get; set; } public virtual Department Department { get; set; } } public class Department { public int DepartmentID { get; set; } public string Name { get; set; } public virtual ICollection<Employee> Employees { get; set; } } |
Note that navigational property in the employee class returns the reference to the department object. The navigational property in Department class returns the employee’s collection. Code first uses this information to determine which class is dependent on which.
Configure One to Many Relationship in Entity Framework
Many to Many Relationship
The Relationship between siblings is Many to Many relationships. Each of your siblings can have many siblings
The relationship between employee and projects is many to many. The employee can be part of more than one project. The Projects can have many employees. The Many to Many relationships usually involves the creation of a join table. The join table will have a composite primary key consisting combination of the primary key of the both employees and project table.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class Employee { public int EmployeeID { get; set; } public string Name { get; set; } //Navigational Property public virtual ICollection<Project> Projects { get; set; } } public class Project { public int ProjectID { get; set; } public string Name { get; set; } //Navigational Property public virtual ICollection<Employee> Employees { get; set; } } |
Configure Many to Many relationships in Entity Framework
Configuring the Relationship in Entity Framework
The Relationships in entity framework can be done using the following methods
Default Conventions
We learned about EF Core Conventions from the Tutorial. The conventions use the default rules to build a model based on your domain classes. EF Core infers the relationships using the navigational properties and use the Conventions and builds the model.
Data Annotations Attributes
Data Annotations allow us to fine tune the model by Attributes. Key Attribute & ForeginKey Attributes are used to further configure the relationship between models
Fluent API
Fluent API Provides more power to configure the relationships in entity models. The Modelbuilder returns the PropertyBuilder to configure the entities. The PropertyBuilder exposes HasOne,HasMany, WithOne, WithMany methods which used to configure relationships. The method to be used depends on the type of relationship (one or many). These methods take navigational properties as their parameter
HasOne
Starts the Configuration of a relationship where the selected entity type has a reference navigation property that points to a single instance of the other type in the relationship.
HasMany
Starts the configuration of a relationship where the selected entity type has a collection navigation property that points to a single instance of the other type in the relationship.
WithOne
This chained after the HasOne/HasMany and completes the Configuration of the relationship as either one-to-one or one-to-many
WithMany
This chained after the HasOne and completes the Configuration of the relationship as either one-to-one or one-to-many.
HasMany/WithMany is not yet supported in EF Core
Reference
In the next tutorials, we will explore each of three relationships in detail.
This would be much more useful if it included examples of how to query this kind of model.
Very well explained! Really appreciate. 🙂
Well explained. Just what I need to understand the difference and implementation. Thanks.
Can you leave some coding examples where you navigate through the properties? I used Fluent API to build the relationships, I tried annotations and the default conventions but all my properties still return null.