En el diseño de bases de datos, una relación uno a uno (1:1) ocurre cuando un registro en una tabla está asociado con exactamente un registro en otra tabla.
Este tipo de relación es útil para segmentación de información (por ejemplo, entidades que están íntimamente relacionadas, pero son cosas diferentes).
Supongamos que tenemos dos entidades:
UserProfile
Cada usuario tiene exactamente un perfil, y cada perfil pertenece a un solo usuario.
public class User
{
public int Id { get; set; }
public string Username { get; set; } // Para login
public string Email { get; set; } // Para autenticación
public string PasswordHash { get; set; } // Seguridad
public Profile Profile { get; set; } // Propiedad de navegación
}
public class Profile
{
public int Id { get; set; }
public string FullName { get; set; } // Nombre completo
public DateTime BirthDate { get; set; } // Fecha de nacimiento
public string Bio { get; set; } // Biografía corta
public User User { get; set; } // Propiedad de navegación
}
¿Por qué no poner todo en User?
En este ejemplo podemos decidir tener las entidades separadas por segregación de datos (es decir, por limpieza)
- ✅
Usercontiene solo la información necesaria para la autenticación y seguridad del sistema, - ✅
Profile, en cambio, guarda datos sobre la persona asociada al User
Otro ejemplo claro lo verás en una relación 1:1 podría ser Empleado y Ordenador. Aunque un empleado pueda tener un solo ordenador, y un ordenador una única persona, son entidades separadas.
Configurar la relación
Estructura de la base de datos generada
Al aplicar una migración, EF crea las tablas:
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 garantiza la relación 1:1!
FOREIGN KEY (UserId) REFERENCES Users(Id)
);
UserId en Profiles es UNIQUE, lo que evita que un mismo usuario tenga múltiples perfiles
Ejemplos practicos
Consulta de datos
Recuperamos un usuario con su perfil:
using (var context = new AppDbContext())
{
// Carga explícita (2 consultas)
var user = context.Users.First(u => u.Id == 1);
var profile = context.Profiles.First(p => p.UserId == user.Id);
// Carga ansiosa (1 consulta con JOIN)
var userWithProfile = context.Users
.Include(u => u.Profile) // JOIN automático
.First(u => u.Id == 1);
Console.WriteLine($"Usuario: {userWithProfile.Username}");
Console.WriteLine($"Nombre completo: {userWithProfile.Profile.FullName}");
}
Inserción de datos
Creamos un usuario con su perfil:
using (var context = new AppDbContext())
{
var newUser = new User { Username = "johndoe" };
var newProfile = new Profile { FullName = "John Doe" };
// Asignamos la relación
newUser.Profile = newProfile;
context.Users.Add(newUser);
context.SaveChanges(); // Guarda ambos registros en la BD
}
