Configure One-to-Zero-or-One Relationship in Entity Framework 6:

Here, you will learn to configure One-to-Zero-or-One relationship between two entities.

We will implement One-to-Zero-or-One relationship between the following Student and StudentAddress entities.

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }
}
     
public class StudentAddress 
{
    public int StudentAddressId { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

Visit Entity Relationship section to understand how EF manages one-to-one, one-to-many, and many-to-many relationships.

A one-to-zero-or-one relationship happens when a primary key of one table becomes PK & FK in another table in relational database such as SQL Server. So, we need to configure above entities in such a way that EF creates Students and StudentAddresses table in the DB and make StudentId column in Student table as PrimaryKey (PK) and StudentAddressId column in StudentAddresses table as PK and ForeignKey (FK) both.

Configure One-to-Zero-or-One Relationship using Data Annotation Attributes:

Here, we will apply DataAnnotations attributes on Student and StudentAddress entities to establish one-to-zero-or-one relationship.

The Student entity follows the default code-first convention as it includes StudentId property which will be key property. So, we don't need to apply any attributes on it because EF will make StudentId column as a PrimaryKey in the Students table in the database.

For the StudentAddress entity, we need to configure StudentAddressId as PK & FK both. StudentAddressId property follows the default convention for primary key. So we don't need to apply any attribute for PK. However, we also need to make it a foreign key which points to StudentId of Student entity. So, apply [ForeignKey("Student")] on StudentAddressId property which will make it foreign key for Student entity as shown below.

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }
}
     
public class StudentAddress 
{
    [ForeignKey("Student")]
    public int StudentAddressId { get; set; }
        
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

Thus, you can use data annotation attribute to configure one-to-zero-or-one relationship between two entities.

Note: Student include StudentAddress navigation property and StudentAddress includes Student navigation property. With one-to-zero-or-one relationship, Student can be saved without StudentAddress but StudentAddress entity cannot be saved without Student entity. EF will throw an exception if you try to save StudentAddress entity without Student entity.

Configure One-to-Zero-or-One relationship using Fluent API:

Here, we will use Fluent API to configure one-to-zero-or-one relationship between Student and StudentAddress entities.

The following example sets one-to-zero or one relationship between Student and StudentAddress using Fluent API.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure Student & StudentAddress entity
    modelBuilder.Entity<Student>()
                .HasOptional(s => s.Address) // Mark Address property optional in Student entity
                .WithRequired(ad => ad.Student); // mark Student property as required in StudentAddress entity. Cannot save StudentAddress without Student
}

In the above example, we start with the Student entity. The HasOptional() method configures the Address navigation property in Student entity as optional (not required when saving Student entity). Then, the WithRequired() method makes the Student navigation property of StudentAddress as required (required when saving StudentAddress entity. It will throw an exception when StudentAddress entity will be saved without Student navigation property). This will make StudentAddressId as ForeignKey also.

Thus, you can configure One-to-Zero-or-one relationship between two entities where Student entity can be saved without attaching StudentAddress object to it but StudentAddress entity cannot be saved without attaching an object of Student entity. This makes one end required.

EF API will create the following tables in the database.

one-to-one relationship in code first

Configure One-to-One relationship using Fluent API:

We can configure One-to-One relationship between entities using Fluent API where both ends are required, meaning Student entity object must include StudentAddress entity object and StudentAddress entity must include Student entity object in order to save it.

Note:One-to-one relationship is technically not possible in MS SQL Server. It will always be one-to-zero or one. EF forms One-to-One relationships on entities not in DB.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure StudentId as FK for StudentAddress
    modelBuilder.Entity<Student>()
                .HasRequired(s => s.Address) 
                .WithRequiredPrincipal(ad => ad.Student); 

}

In the above example, modelBuilder.Entity<Student>().HasRequired(s => s.Address) makes Address property of StudentAddress is required and .WithRequiredPrincipal(ad => ad.Student) makes Student property of StudentAddress entity as required. Thus it configures both ends as required. So now, when you try to save Student entity without address or StudentAddress entity without Student, it will throw an exception.

Create read-only Entity Data Model for the above example using EF Power Tools. The entities will appear like the diagram shown below:

one-to-one relationship in code first

Learn how to configure a one-to-many relationship in the next section.


Test Your Entity Framework Knowledge: