Entity Framework (EF) Code First Cascade Delete for One-to-Zero-or-One relationship


Siguiendo la sección "Code First Modeling" del curso Pluralsight "Getting Started with Entity Framework 5" de Julie Lerman, creé dos clases POCO con una relación de uno a cero o uno: un padre (User) y un hijo opcional (UserDetail).

Diagrama de modelo de datos de usuario y usuario detallado (haga clic para ver).

Observe en el diagrama que la propiedad userId es una clave primaria y una clave foránea para UserDetail .

Código pertinente:

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 de usuario en la base de datos porque la clave foránea en UserDetail no tiene activada 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 relaciones de uno a cero o uno usando Entity Framework Código Primero (de modo que al eliminar un Usuario automáticamente se borra UserDetail)?

Author: arsenalogy, 2013-07-05

3 answers

Tendrá que usar la API fluent 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);
}
 67
Author: hutchonoid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-20 21:47:50

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 era:

public override void Up()
    {
        AddForeignKey("UserDetail", "UserId", "User", "UserId", cascadeDelete: true);
    }

Y funcionó bien. Cuando usé

modelBuilder.Entity<User>()
    .HasOptional(a => a.UserDetail)
    .WithOptionalDependent()
    .WillCascadeOnDelete(true);

El código de migración era:

AddForeignKey("User", "UserDetail_UserId", "UserDetail", "UserId", cascadeDelete: true); 

Pero no coincide con ninguna de las dos sobrecargas disponibles (en EntityFramework 6)

 1
Author: Lupa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-09 00:29:57

También puede desactivar la convención de eliminación en cascada en el ámbito global de su aplicación haciendo esto:

modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>()
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>()
 0
Author: rajeemcariazo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-11 02:03:26