Entity Framework Core One-to-One Relationship

Jasmine
4 min readJul 11, 2023

--

With Entity Framework Core’s one-to-one relationship support, you can effortlessly express and manage relationships where each entity is uniquely tied to another entity, ensuring consistent data integrity. Let’s explore it in detail.

Imagine we have two classes: “Employee” and “EmployeeDetails”

public class Employee
{
public int EmployeeId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}

public class EmployeeDetails
{
public int DetailsId { get; set; }
public int EmployeeId { get; set; }
public string Email { get; set; }
}

The Employee class represents an employee and the EmployeeDetails class represents the details of an employee. We will establish an one-to-one relationship between two classes. This one-to-one relationship allows you to store and retrieve additional details for each employee, such as their email address, by accessing the Details property of the Employee class. It ensures that each employee has a unique set of details, and the relationship is established through the common EmployeeId property between the two classes.

Conventions

public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

public EmployeeDetails EmployeeDetails { get; set; }
}

public class EmployeeDetails
{
public int Id { get; set; }
public string Email { get; set; }

public int EmployeeId { get; set; }
public Employee Employee { get; set; }
}
  • EmployeeId property in EmployeeDetails class: An integer property representing the identifier of the corresponding employee. It is identified as a foreing key.
  • Employee property in EmployeeDetails class: An instance of the Employee class representing the associated employee.
  • EmployeeDetails property in Employee class: An instance of the EmployeeDetails class representing additional details of the employee.

Each Employee object can have a single corresponding EmployeeDetails object. The EmployeeDetails object is accessed through the EmployeeDetails property of the Employee class.

Fluent API

In such cases where EF Core conventions cannot accommodate your requirements, Fluent API provides a way to explicitly configure the mapping, relationships, constraints, and other aspects of your entities, allowing you to tailor the behavior of EF Core to fit your specific needs.

public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

public EmployeeDetails EmployeeDetails { get; set; }
}

public class EmployeeDetails
{
public int Id { get; set; }
public string Email { get; set; }

public int Employee_Id { get; set; }
public Employee Employee { get; set; }
}

In your DbContext class, override the OnModelCreating method and use Fluent API to configure the one-to-one relationship:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.HasOne(e => e.EmployeeDetails)
.WithOne(ed => ed.Employee)
.HasForeignKey<EmployeeDetails>(ed => ed.Employee_Id);
}
  • HasOne specifies that the Employee entity has one related EmployeeDetails entity.
  • WithOne specifies that the EmployeeDetails entity has one related Employee entity.
  • HasForeignKey specifies the foreign key property Employee_Id in the EmployeeDetails entity that links to the primary key Id in the Employee entity.

Data Annotations

public class Employee
{
[Key]
public int EmployeeId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

public EmployeeDetails EmployeeDetails { get; set; }
}

public class EmployeeDetails
{
[Key]
public int EmployeeDetailsId { get; set; }
public string Email { get; set; }

public int EmployeeId { get; set; }
[ForeignKey("Employee")]
public Employee Employee { get; set; }
}

We use the [ForeignKey("Employee")] attribute on the EmployeeId property to specify the foreign key constraint, indicating that it references the Employee navigation property in the EmployeeDetails class.

Shared Primary Key Approach

When working with one-to-one relationships in Entity Framework Core (EF Core), one of several best practice approaches is shared primary key approach.

In some scenarios, you may want to use a shared primary key between the two entities in a one-to-one relationship. This means that the primary key of one entity is also used as the primary key and foreign key in the other entity. This can simplify the relationship and eliminate the need for an additional foreign key property.

Implementation using data annotations:

public class Employee
{
[Key]
public int Id { get; set; }
public string Name { get; set; }

public EmployeeDetails EmployeeDetails { get; set; }
}

public class EmployeeDetails
{
[Key,ForeignKey("Employee")]
public int Id { get; set; }
public string Email { get; set; }

public Employee Employee { get; set; }
}

Implementation using Fluent API:

public class Employee
{
public int Id { get; set; }
public string Name { get; set; }

public EmployeeDetails EmployeeDetails { get; set; }
}

public class EmployeeDetails
{
public int Id { get; set; }
public string Email { get; set; }

public Employee Employee { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Employee>()
.HasOne(e => e.EmployeeDetails)
.WithOne(ed => ed.Employee)
.HasForeignKey<EmployeeDetails>(ed => ed.Id);

// Additional configurations or entities...

base.OnModelCreating(modelBuilder);
}

You can check my other article.

--

--