We are going to look at how to Configure one to one relationship in entity framework core using Convention, Data Annotations & Fluent API.
Table of Contents
One to One relationship in Entity Framework Core
Let us take the example of an Employee and EmployeeAddress domain models and create a One to One relationship between them. In a One to one relationship PrimaryKey of the Primary table (employeeID of employee table) is both Primary key and Foreign key in the dependent table (EmployeeAddress).
Basic Model
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 { public int EmployeeID { get; set; } public string Address { get; set; } // //Navigation property Returns the Employee object public virtual Employee Employee { get; set; } } |
Note that the 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.
One to One Relationship using Default Convention
The Navigational property in both the classes returns the object. This makes it difficult for the Entity framework, to determine which class is dependent on which. Hence Setting up the One to One Relationship using default convention is not straightforward.
The EmployeeAddress class uses the EmployeeID as both Primary key & Foreign Key. The Convention requires us to have
So by Adding the public int id { get; set; } we are able to trick EF Core to create the one to one relationship for us
One to One Relationship using Data Annotations
In Convention, we added id property into the EmployeeAddress table to trick EF Core to set up the relationship for us. The Data Annotations has ForeignKey and Key Attributes which you can use to create the relationships.
Hence we use Primary Key Attribute on EmployeeID property in EmployeeAddress class (Dependent). Our EmployeeAddress class will look like this
1 2 3 4 5 6 7 8 9 10 11 | public class EmployeeAddress {   [Key]   public int EmployeeID { get; set; }   public string Address { get; set; } //   //Navigation property Returns the Employee object   public virtual Employee Employee { get; set; } } |
Now, what if you want to change the name of the EmployeeID to EmpID. In that case, we need to use the ForeignKey Attribute as shown below
1 2 3 4 5 6 7 8 9 10 11 | public class EmployeeAddress { [Key, ForeignKey("Employee")] public int EmpID { get; set; }t; } public string Address { get; set; } //Navigation property Returns the Employee object public Employee Employee { get; set; } } |
One to One Relationship using Fluent API
The Fluent API Provides four methods to define the navigational properties
- HasOne
- HasMany
- WithOne
- WithMany
The One/Many signifies one or many relationships.
We always begin with HasOne/HasMany on the entity on which you are configuring. We then chain it with WithOne/WithMany to configure the other side of the relationship
Now, let us use the Fluent API to configure the one to one relationship. Remove all the conventions & Data Annotations attributes applied.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public class Employee { public int EmployeeID { get; set; } public string Name { get; set; } //Navigation property Returns the Employee Address public EmployeeAddress EmployeeAddress { get; set; } } public class EmployeeAddress { public int EmployeeID { get; set; } public string Address { get; set; } //Navigation property Returns the Employee object public Employee Employee { get; set; } } |
Since, we do not have Primary Key defined on EmployeeAddress class, let us define it first using HasKey method
1 2 3 4 | modelBuilder.Entity<EmployeeAddress>() .HasKey(s => s.EmployeeID); |
Next, we start by configuring the Employee entity.
1 2 3 | modelBuilder.Entity<Employee>() |
Since the Employee class is belongs to “One” side of the relation, we will need HasOne method. The HasOne requires us to specify the Navigation Property (i.e. EmployeeAddress) of the Employee Class (i.e. entity being configured)
1 2 3 | .HasOne<EmployeeAddress>(p => p.EmployeeAddress) |
Finally, we move one to the other end of the relationship (i.e EmployeeAddress), which is also “one” side of the relation. Hence we will use
1 2 3 | .WithOne(s => s.Employee); |
The Final Code
1 2 3 4 5 6 7 8 | modelBuilder.Entity<EmployeeAddress>() .HasKey(s => s.EmployeeID); modelBuilder.Entity<Employee>() .HasOne<EmployeeAddress>(p => p.EmployeeAddress) .WithOne(s => s.Employee); |
In the example above, we started with the Employee class. We can also start with the EmployeeAddress class to achieve the same result as shown below
1 2 3 4 5 6 7 8 | modelBuilder.Entity<EmployeeAddress>() .HasKey(s => s.EmployeeID); modelBuilder.Entity<EmployeeAddress>() .HasOne<Employee>(p => p.Employee) .WithOne(s => s.EmployeeAddress); |
Using Foreign Key Field Name
We can use a another field for Foreign Key. For Example consider our EmployeeAddress class as
1 2 3 4 5 6 7 8 9 10 11 | public class EmployeeAddress { public int ID { get; set; } public string Address { get; set; } //Navigation property Returns the Employee object public int EmpID { get; set; } public Employee Employee { get; set; } } |
1 2 3 4 5 6 7 8 9 | modelBuilder.Entity<EmployeeAddress>() .HasKey(s => s.ID); modelBuilder.Entity<Employee>() .HasOne<EmployeeAddress>(p => p.EmployeeAddress) .WithOne(s => s.Employee) .HasForeignKey<EmployeeAddress>(s => s.EmpID); |
We invoke the HasForeignKey method to sepecify the EmpID As the ForeignKey
Conclusion
The above sets up the One to One Relationship using Data annotations & Fluent API. In the next tutorial let us look at how to Configure the One to Many Relationship
how to do as command below in ef core
UPDATE table1 SET filed1=’value1′,field1=’value2′ WHERE id=1 AND id2=4