Search code examples
c#entity-frameworkmany-to-many

Entity Framework 6 preventing deletion


How do you make EF not allow deletion of a related entity? eg:

public class Enrollment 
{
    public int EnrollmentId { get; set; }
    public virtual ICollection<Course> courses { get; set; }
}

public class Course 
{
    public int CourseId { get; set; }
    public string Name { get; set; }
}

When I create a Course A and B, and then I create an Enrollment and add those courses to it, I need it to not allow me to delete Courses A or B. When I run it through my MVC controller this has no problem:

Course course = db.Courses.Find(id);
db.Courses.Remove(course);
db.SaveChanges();

I'm not even sure exactly what to search for. I think it's enforcing or enabling a many to many referential constraint? But I don't seem to find anything. Am I supposed to not expect it to make that constraint automatically? I figured I could always add the following line to the Delete controller:

if(db.Enrollments.Any(e => e.Courses.Any(c => c.CourseId == id)))
{ //error }

Also, trying the following fluentAPI wasn't working (among many variations):

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Enrollment>()
               .HasMany<Course>(e => e.Courses)
               .WithRequired()
               .WillCascadeOnDelete(false);
        modelBuilder.Entity<Course>()
               .HasMany(e => e.Enrollments);
        base.OnModelCreating(modelBuilder);
    }

Solution

  • How do you make EF not allow deletion of a related entity?

    You want to prevent deleting things that is in used, right? Is course and enrollments a many to many relationship? Many to many will not cascade on delete by default. Try to change to this.

    public class Enrollment 
    {
        public int EnrollmentId { get; set; }
        public virtual ICollection<Course> Courses { get; set; }
    }
    
    public class Course 
    {
        public int CourseId { get; set; }
        public string Name { get; set; }
        public virtual ICollection<Enrollment> Enrollments { get; set; }
    }
    
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Need this to remove the cascade convention.
        modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
    }