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).
Let’s assume we have two entities:
UserProfile
Each user has exactly one profile, and each profile belongs to a single 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)
- ✅
Usercontains only the information necessary for system authentication and security, - ✅
Profile, on the other hand, stores data about the person associated with the User
Another clear example you’ll see in a 1:1 relationship could be Employee and Computer. Although an employee can have only one computer, and a computer can have only one person, they are separate entities.
Configuring the Relationship
Generated Database Structure
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
Querying Data
Retrieve a user with their profile:
using (var context = new AppDbContext())
{
// Explicit loading (2 queries)
var user = context.Users.First(u => u.Id == 1);
var profile = context.Profiles.First(p => p.UserId == user.Id);
// Eager loading (1 query with JOIN)
var userWithProfile = context.Users
.Include(u => u.Profile) // Automatic JOIN
.First(u => u.Id == 1);
Console.WriteLine($"User: {userWithProfile.Username}");
Console.WriteLine($"Full Name: {userWithProfile.Profile.FullName}");
}
Inserting Data
Create a user with their profile:
using (var context = new AppDbContext())
{
var newUser = new User { Username = "johndoe" };
var newProfile = new Profile { FullName = "John Doe" };
// We assign the relationship
newUser.Profile = newProfile;
context.Users.Add(newUser);
context.SaveChanges(); // Saves both records to the DB
}
