c# - Código Entity Framework(EF) First Cascade Delete para la relación One-Zero-One
ef core on delete no action (3)
Deberá usar la API fluida para hacer esto.
Intente agregar lo siguiente a su DbContext
:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.HasOptional(a => a.UserDetail)
.WithOptionalDependent()
.WillCascadeOnDelete(true);
}
Siguiendo la sección "Modelar primero el código" del curso Pluralsight "Comenzando con Entity Framework 5" por Julie Lerman , creé dos clases POCO con una relación uno a cero o uno : un padre (usuario) y un opcional niño (UserDetail).
Diagrama del modelo de datos de usuario y de usuario (haga clic para ver).
Observe en el diagrama que la propiedad UserId es una clave principal y una clave externa para UserDetail .
Código relevante:
public class User
{
//...
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
/* Has a 1:0..1 relationship with UserDetail */
public virtual UserDetail UserDetail { get; set; }
//...
}
public class UserDetail
{
//...
/* Has a 0..1:1 relationship with User */
public virtual User User { get; set; }
[Key, ForeignKey("User")]
public int UserId { get; set; }
//...
}
public class EFDbContext : DbContext
{
public DbSet<User> Users { get; set; }
//public DbSet<UserDetail> UserDetails { get; set; } /* Explicit declaration not necessary. Context is aware of UserDetail entity due to 0..1:1 relationship with User */
public EFDbContext()
{
Configuration.ProxyCreationEnabled = true;
Configuration.LazyLoadingEnabled = true;
}
}
public class UserRepository : IUserRepository
{
private EFDbContext _context = new EFDbContext();
public void Delete(User entity)
{
entity = _context.Users.Find(entity.UserId);
//...
_context.Users.Remove(entity);
_context.SaveChanges();
//...
}
}
Cuando se llama al método Delete () en la clase UserRepository, no elimina el registro User en la base de datos porque la clave foránea en UserDetail no tiene habilitada la eliminación en cascada.
La instrucción DELETE entró en conflicto con la restricción de REFERENCIA "FK_dbo.UserDetail_dbo.User_UserId".
¿Cómo habilitaría las eliminaciones en cascada para las relaciones de uno a cero o uno usando primero el Código del Entidad Framework (para que al eliminar un Usuario se elimine automáticamente UserDetail)?
Este código funcionó para mí
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<UserDetail>()
.HasRequired(d => d.User)
.WithOptional(u => u.UserDetail)
.WillCascadeOnDelete(true);
}
El código de migración fue:
public override void Up()
{
AddForeignKey("UserDetail", "UserId", "User", "UserId", cascadeDelete: true);
}
Y funcionó bien. Cuando utilicé por primera vez
modelBuilder.Entity<User>()
.HasOptional(a => a.UserDetail)
.WithOptionalDependent()
.WillCascadeOnDelete(true);
El código de migración fue:
AddForeignKey("User", "UserDetail_UserId", "UserDetail", "UserId", cascadeDelete: true);
pero no coincide con ninguna de las dos sobrecargas disponibles (en EntityFramework 6)
También puede desactivar la convención de eliminación en cascada en el alcance global de su aplicación haciendo esto:
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>()