entity-framework-relaciones-uno-a-uno

One-to-One Relationships in Entity Framework

  • 4 min

In database design, a one-to-one (1:1) relationship occurs when a record in one table is associated with exactly one record in another table.

This type of relationship is useful for information segmentation (for example, entities that are closely related but are different things).

Suppose we have two entities:

  • User
  • Profile

Each user has exactly one profile, and each profile belongs to one user.

public class User
{
    public int Id { get; set; }
    public string Username { get; set; }         // For login
    public string Email { get; set; }            // For authentication
    public string PasswordHash { get; set; }     // Security

    public Profile Profile { get; set; } // Navigation property
}

public class Profile
{
    public int Id { get; set; }
    public string FullName { get; set; }         // Full name
    public DateTime BirthDate { get; set; }      // Birth date
    public string Bio { get; set; }              // Short bio

    public User User { get; set; } // Navigation property
}

Why not put everything in User?

In this example, we can decide to have the entities separated for data segregation (i.e., for cleanliness)

  • User contains only the necessary information for system authentication and security,
  • Profile, on the other hand, holds data about the person associated with the User

Another clear example of a 1:1 relationship could be Employee and Computer. Even though an employee may have only one computer, and one computer belongs to a single person, they are separate entities.

Configuring the relationship

Naming conventions

Entity Framework can infer the 1:1 relationship if:

  • Both entities have a navigation property pointing to the other.
  • One of the entities has a foreign key that follows the convention {PrimaryKeyName}Id.
public class Profile
{
    public int Id { get; set; }
    public string FullName { get; set; }
    public int UserId { get; set; } // Foreign key (UserId → User.Id)
    public User User { get; set; } // Navigation property
}

EF automatically detects that Profile.UserId is a foreign key of User.Id

With Data Annotations

If we do not follow the conventions, we can use attributes:

[ForeignKey] on the foreign key

public class Profile
{
    public int Id { get; set; }
    public string FullName { get; set; }

    [ForeignKey("User")] // Indicates that UserId is FK of User
    public int UserId { get; set; }

    public User User { get; set; }
}

[ForeignKey] on the navigation property

public class Profile
{
    public int Id { get; set; }
    public string FullName { get; set; }
		
    public int UserId { get; set; }

    [ForeignKey("UserId")] // Indicates that UserId is the FK
    public User User { get; set; }
}

With Fluent API

Or we can also configure it with Fluent API.

Foreign key in Profile

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .HasOne(u => u.Profile)       // A User has a Profile
        .WithOne(p => p.User)         // A Profile belongs to a User
        .HasForeignKey<Profile>(p => p.UserId); // FK in Profile
}

Foreign key in User (less common)

modelBuilder.Entity<Profile>()
    .HasOne(p => p.User)
    .WithOne(u => u.Profile)
    .HasForeignKey<User>(u => u.ProfileId); // FK in User

Structure of the generated database

When applying a migration, EF creates the tables:

CREATE TABLE Users (
    Id INT PRIMARY KEY IDENTITY,
    Username NVARCHAR(100)
);

CREATE TABLE Profiles (
    Id INT PRIMARY KEY IDENTITY,
    FullName NVARCHAR(100),
    UserId INT UNIQUE, -- UNIQUE guarantees the 1:1 relationship!
    FOREIGN KEY (UserId) REFERENCES Users(Id)
);

UserId in Profiles is UNIQUE, which prevents the same user from having multiple profiles

Practical examples