[Entity Framework][Code First]Cascade Delete

Cascade Delete

前言

連動刪除在兩個有關係的table之間常常會用到,例如我刪除Student資料,也要連Course資料一起刪除。  

在這邊先介紹兩種連動刪除的方式

  • Client-Side Cascade Delete
  • Sql Cascade Delete

今天的範例關係Domain Class,Student與Course是個一對多的關係,如下:

public class Student
{
    public int StudentId { get; set; }

    public string Name { get; set; }

    public ICollection<Course> Courses { get; set; }
}

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

    public string Name { get; set; }

    public int StudentId { get; set; }

    public Student Student { get; set; }
}

 

Client-Side Cascade Delete

如果要讓Entity Framework做到連動刪除,則要使用eager loading,才能讓Entity Framework幫妳做到連動刪除。

var student = db.Student
            .Include("Courses") //eager loading
            .FirstOrDefault(x => x.Name.Equals("Miles"));

db.Student.Remove(student);

db.SaveChanges();

使用eager loading刪除的話,Entity Framework會先執行刪除Course的指令,在執行刪除Student指令,如下:

Sql Cascade Delete

基本上Client-Side Cascade Delete是給資料庫沒有支援Cascade Delete的時候方便的。  而MSSQL外部索引鍵設定,裡面可以設定刪除規則,只要將刪除規則設為重疊顯示(Cascade),則只要刪除Student,Course的資料就會自動被刪除,就不需要使用Client-Side Cascade Delete產生多個刪除指令,效能會更好。 

只要把eager loading那行拿掉,Client-Side Cascade Delete的功能就會拿掉了。  拿掉後Entity Framework就只會產生一行刪除指令,此時Cascade Delete的責任就是交給資料庫處理了。

var student = db.Student            
            .FirstOrDefault(x => x.Name.Equals("Miles"));

db.Student.Remove(student);

db.SaveChanges();

 

Cascade Delete with Fluent Configuration

Cascade Delete 預設是會啟動的。  如果要拿掉Sql Cascade跟Client-Side Cascade Delete,可用WillCascadeOnDelete(false)設定。  當設定為false後,不管有沒有eager loading,刪除的時候都只會產生Delete Student的指令。

public class CourseConfiguration : EntityTypeConfiguration<Course>
{
    public CourseConfiguration()
    {
        HasRequired<Student>(x => x.Student)
            .WithMany(x => x.Courses)
            .HasForeignKey<int>(x => x.StudentId)
            .WillCascadeOnDelete(false);
    }
}

備註:WillCascadeOnDelete()的設定也會影響到資料庫的刪除規則,如果設定false,則資料庫就不會有Cascade Delete的功能,如下圖:

 

注意:

只是如果把Cascade Delete拿掉的話,會變成無法單除刪除Student,因為只要該Student有Course資料的話,只要一刪除就會出現以下錯誤。  除非自行手動先刪除Course才能完整刪除資料。

The DELETE statement conflicted with the REFERENCE constraint "FK_dbo.Courses_dbo.Students_StudentId". The conflict occurred in database "DefaultConvetion.Model1", table "dbo.Courses", column 'StudentId'

 

 

 

 

一天一分享,身體好健康。

該追究的不是過去的原因,而是現在的目的。