arsenalogy arsenalogy - 1 month ago 11
C# Question

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

Following the "Code First Modeling" section of the Pluralsight "Getting Started with Entity Framework 5" course by Julie Lerman, I created two POCO classes with a one-to-zero-or-one relationship: a parent (User) and an optional child (UserDetail).

User and UserDetail data model diagram (click to view).

Notice in the diagram that the UserId property is a primary key and a foreign key for UserDetail.

Relevant code:

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();

//...
}
}


When the Delete() method in the UserRepository class is called, it does not delete the User record in the database because the foreign key in UserDetail does not have cascade delete enabled.


The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.UserDetail_dbo.User_UserId".


How would you enable cascading deletes for one-to-zero-or-one relationships using Entity Framework Code First (so that deleting a User automatically deletes UserDetail)?

Answer

You will have to use the fluent API to do this.

Try adding the below to your DB Context

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {

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