One-to-One Relationships in Entity Framework Core

One-to-One Relationships in Entity Framework Core using Fluent API

In this article, I am going to discuss How to configure One-to-One Relationships between two entities in Entity Framework Core (EF Core) using Fluent API with Examples. Please read our previous article discussing Relationships Between Entities in EF Core.

One-to-One Relationships in Entity Framework Core

In the One-To-One relationship, a row in Table A can have no more than one matching row in Table B, and vice versa. A one-to-one relationship is created if both of the related columns are primary keys or have unique constraints. In the one-to-one relationship, the primary key acts additionally as a foreign key, and there is no separate foreign key column.

EF Core establishes a one-to-one relationship when both entities have a reference navigation property pointing to the other entity. Annotations like [ForeignKey] and [InverseProperty] are often used to define the relationship explicitly, and we have already discussed these things. In this article, I am going to discuss How to Implement One-to-One Relationships in EF Core using Fluent API Configuration.

Examples of Understanding One-to-One Relationships in EF Core

In Entity Framework Core (EF Core), you can define a one-to-one relationship between entities using the Fluent API. The Fluent API provides a way to configure the relationships and mappings between entities in a more flexible and detailed manner than using only data annotations.

Let us understand this with an example. We are going to implement One-to-Zero or One-to-One relationship between the following Student and StudentAddress entities.

Student.cs

So, first, create a class file with the name Student.cs and then copy and paste the following code into it.

namespace EFCoreCodeFirstDemo.Entities
{
    public class Student
    {
        public int StudentId { get; set; }
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        public virtual Address? Address { get; set; }
    }
}
Address.cs

Next, create another class file with the name Address.cs and then copy and paste the following code into it.

namespace EFCoreCodeFirstDemo.Entities
{
    public class Address
    {
        public int AddressId { get; set; }
        public string? AddressLine1 { get; set; }
        public string? AddressLine2 { get; set; }
        public int PinCode { get; set; }
        public string? City { get; set; }
        public string? State { get; set; }
        public string? Country { get; set; }
        public virtual Student? Student { get; set; }
    }
}

When the Primary Key (PK) of one table becomes the Primary Key (PK) and Foreign Key (FK) in another table in a relational database such as SQL Server, MySQL, Oracle, etc., then it is said to be in a One-to-One or One-to-Zero relationship between the two database tables.

So, we need to configure the above Student and Address entities in such a way that EF Core should create the Students and Addresses tables in the Database and makes the StudentId column in the Students table as the Primary Key (PK) and AddressId column in the Addresses table as Primary Key (PK) and Foreign Key (FK).

Note: In the One-To-One or One-To-Zero relationship, a row in Table A can have a maximum of one or zero matching rows in Table B, and vice versa is also true.

How to Configure One-to-One Relationships Using EF Core Fluent API?

We can configure the One-to-One required relationship between two entities using both Data Annotation Attribute and Fluent API. We have already discussed configuring One to One relationship between the two entities using the ForeignKey Data Annotation Attribute.

Now, let us proceed and try to understand how to Configure One-to-One relationships between two entities using Entity Framework Core Fluent API. To implement this, we need to use the following HasOne(), WithOne, HasForeignKey, and IsRequired() Fluent API methods.

  1. HasOne(): It configures a relationship where this entity type has a reference that points to a single instance of the other entity in the relationship.
  2. WithOne(): Configures this as a one-to-one relationship.
  3. HasForeignKey(): It configures the property(s) to use as the foreign key for this relationship. That means it specifies the dependent entity’s foreign key property name.
  4. IsRequired(): It configures whether this is a required relationship, i.e., whether the foreign key property(s) can be assigned. By default, its value is true. We can also set this value to false if we want to make the relationship optional.

Next, modify the context class as follows. The following code sets a one-to-one required relationship between the Student and Address entities using Entity Framework Core Fluent API.

using Microsoft.EntityFrameworkCore;
namespace EFCoreCodeFirstDemo.Entities
{
    public class EFCoreDbContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            //Configuring the Connection String
            optionsBuilder.UseSqlServer(@"Server=LAPTOP-6P5NK25R\SQLSERVER2022DEV;Database=EFCoreDB;Trusted_Connection=True;TrustServerCertificate=True;");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // Configure One to One Relationships Between Student and Address
            modelBuilder.Entity<Student>()
           .HasOne(s => s.Address) //Student has one Address
           .WithOne(ad => ad.Student) //Address is associated with one Student
           .HasForeignKey<Address>(ad => ad.AddressId) //Foreign key in Address table
           .IsRequired(); //This is a required relationship.
        }

        public DbSet<Student> Students { get; set; }
        public DbSet<Address> Addresses { get; set; }
    }
}

In the context class, we need to configure the relationship using Fluent API within the OnModelCreating method. The following code exactly configures the One-to-One relationship between the Student and Address entities.

How to configure One-to-One Relationships between two entities in Entity Framework Core using Fluent API with Examples

Let’s understand the above code step by step.

  • modelBuilder.Entity<Student>() starts configuring the Student entity. Whichever entity you want to configure using Fluent API, you need to start configuring using the Entity method, and to this generic method, we need to specify the entity type. In this case, it is the Student.
  • HasOne(s => s.Address) method specifies that the Student entity includes one Address reference property using a lambda expression. It configures a relationship where this entity type, i.e., Student entity, has a reference that points to a single instance of the other entity, i.e., Address in the relationship. That means Student has one Address.
  • WithOne(ad => ad.Student) configures the other end of the relationship, the Address entity. It specifies that the Address entity includes a Student type reference navigation property. Configures this as a one-to-one relationship. That means the Address is associated with one Student.
  • HasForeignKey<Address>(ad => ad.AddressId) specifies the foreign key property name. It configures the property, i.e., AddressId, as the foreign key for this relationship. That means it specifies the dependent entity’s foreign key property name.
  • IsRequired(): It configures whether this is a required relationship, i.e., whether the foreign key property(s) can be assigned. By default, its value is true. We can also set this value to false if we want to make the relationship optional. Here, by default, it will make the relationship required.

Note: Before Proceeding further, let us delete the EFCoreDB database using SSMS and Migration folder from our project.

With the above changes in place, open Package Manager Console and Execute the following add-migration and update-database commands. You can give any name to your migration. Here, I am giving EFCoreDBMig1. The name that you are giving it should not be given earlier.

How to configure One-to-One Relationships between two entities in Entity Framework Core using Fluent API

Now, if you verify the database, you should see the following.

How to configure One-to-One Relationships between two entities in EF Core using Fluent API

Next, modify the Main method of the Program class as follows. While creating the student Entity, we have specified the Student Address reference property.

using EFCoreCodeFirstDemo.Entities;
namespace EFCoreCodeFirstDemo
{
    internal class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //Creating an Instance of the Context Class
                using EFCoreDbContext context = new EFCoreDbContext();

                //Creating Address Entity, 
                var studentAddress = new Address() { AddressLine1 = "Text1", AddressLine2 = "Text2"};

                //Creating Student Entity, configuring the Related Student Address Entity
                var student = new Student() { FirstName = "Pranaya", LastName = "Rout", Address = studentAddress };

                context.Students.Add(student);
                context.SaveChanges();
                Console.WriteLine("Student and Address Added");
                Console.ReadKey();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}"); ;
            }
        }
    }
}

Now, run the application and verify the database. You should see both the Student and Address database tables filled with one record, as shown below.

How to configure One-to-One Relationships between two entities in EF Core using Fluent API with Examples

You can start configuring with the Address entity in the same way, as follows.

One-to-One Relationships in EF Core using Fluent API with Examples

So, modify the context class as follows:

using Microsoft.EntityFrameworkCore;
namespace EFCoreCodeFirstDemo.Entities
{
    public class EFCoreDbContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            //Configuring the Connection String
            optionsBuilder.UseSqlServer(@"Server=LAPTOP-6P5NK25R\SQLSERVER2022DEV;Database=EFCoreDB;Trusted_Connection=True;TrustServerCertificate=True;");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            // Configure One to One Relationships Between Student and Address
            // modelBuilder.Entity<Student>()
            //.HasOne(s => s.Address) //Student has one Address
            //.WithOne(ad => ad.Student) //Address is associated with one Student
            //.HasForeignKey<Address>(ad => ad.AddressId) //Foreign key in Address table
            //.IsRequired(); //This is a required relationship.

            // Configure One to One Relationships Between Address and Student
            modelBuilder.Entity<Address>()
           .HasOne(ad => ad.Student) //Address has one Student Navigation Entity
           .WithOne(std => std.Address) //Student is associated with one Address
           .HasForeignKey<Student>(std => std.StudentId) //Foreign key in Student table
           .IsRequired(true); //This is a required relationship.
        }

        public DbSet<Student> Students { get; set; }
        public DbSet<Address> Addresses { get; set; }
    }
}

Note: Before Proceeding further, let us delete the EFCoreDB database using SSMS and Migration folder from our project.

With the above changes in place, open Package Manager Console and Execute the following add-migration and update-database commands. You can give any name to your migration. Here, I am giving EFCoreDBMig1. The name that you are giving it should not be given earlier.

One-to-One Relationships in Entity Framework Core using Fluent API with Examples

Now, if you verify the database, you should see the following.

One-to-One Relationships in Entity Framework Core using Fluent API

If you want to make the relationship as optional, then you need to pass the value false to the IsRequired method, as shown below.

One-to-One Relationships in EF Core using Fluent API

Note: By using the Fluent API, you have more control over the relationship configuration, such as customizing the foreign key property names, specifying cascading delete behavior, and other advanced features. Remember that the Fluent API configuration takes precedence over data annotations when both are used together.

In the next article, I am going to discuss How to Configure One-to-Many Relationships in Entity Framework Core using Fluent API with Examples. Here, in this article, I try to explain How to Configure the One-to-One (Required) or One-to-Zero (Optional) Relationships between Entities in Entity Framework Core Fluent API with Examples. I hope you enjoyed this Configure One-to-One Relationship using EF Core Fluent API article.

Leave a Reply

Your email address will not be published. Required fields are marked *