پیکربندی حذف شدن آبشاری و یا Cascade Delete در Entity Framework Code First


درواقع که منظور از Cascade delete و یا حذف شدن آبشاری این است که در زمان حذف شدن یک رکورد، تمامی رکوردهای مرتبط با آن که اصطلاحاً به آنها dependent record نیز می‌گویند حذف شود. به طور پیش فرض در Entity Framework برای تمامی رابطه هایی که وجود دارند چه از نوع one-to-one باشد و چه از نوع one-to-many و یا many-to-many بحث مربوط به cascade delete فعال شده است.

بررسی Cascade Delete در رابطه های One-To-One

در قسمت های قبلی با کلاس های Student و StudentAddress آشنا شدید. بین این دو کلاس یک رابطه از نوع one-to-zero-or-one وجود دارد. کد مربوط به این موضوع در قسمت زیر نشان داده شده است.

public class Student

{

public int StudentId { get; set; }

public string StudentName { get; set; }

public virtual StudentAddress Address { get; set; }

}

public class StudentAddress

{

[ForeignKey("Student")]

public int StudentAddressId { get; set; }

public string Address1 { get; set; }

public string Address2 { get; set; }

public string City { get; set; }

public int Zipcode { get; set; }

public string State { get; set; }

public string Country { get; set; }

public virtual Student Student { get; set; }

}

علاوه بر این مثالی که در قسمت زیر مشاهده می کنید نحوه انجام عملیات cascade delete را نشان می‌دهد.

using (var ctx = new SchoolContext())

{

var stud = new Student() { StudentName = "James" };

var add = new StudentAddress() { Address1 = "address" };

stud.Address = add;

ctx.Students.Add(stud);

ctx.SaveChanges();

ctx.Students.Remove(stud);// student and its address will be removed from db

ctx.SaveChanges();

}

در مثال بالا در ابتدا یک Student را به همراه StudentAddress مرتبط با آن در دیتابیس ذخیره می کنیم و سپس همان Student را حذف کرده و متد SaveChanges را صدا می‌زنیم. این موضوع باعث می‌شود که Entity Framework نه تنها آن Student را حذف کند؛ بلکه رکورد مربوط به آن یعنی همان StudentAddress را نیز حذف کند. بنابراین Entity Framework در رابطه های one-to-one به طور پیش فرض cascade delete را فعال سازی می کند.

بررسی Cascade Delete در رابطه های One-To-Many

به منظور بررسی کردن گزینه و یا رفتار cascade delete در Entity Framework کلاس های Student و Standard را در قسمت زیر در نظر بگیرید.

public class Student

{

public int StudentId { get; set; }

public string StudentName { get; set; }

public virtual Standard Standard { get; set; }

}

public class Standard

{

public Standard()

{

Students = new List<Student>();

}

public int StandardId { get; set; }

public string Description { get; set; }

public virtual ICollection<Student> Students { get; set; }

}

بین این دو کلاس یک رابطه از نوع one-to-many وجود دارد. مثال زیر نحوه انجام cascade delete را برای این دو کلاس بررسی کرده است.

public class Student

{

public int StudentId { get; set; }

public string StudentName { get; set; }

public virtual Standard Standard { get; set; }

}

public class Standard

{

public Standard()

{

Students = new List<Student>();

}

public int StandardId { get; set; }

public string Description { get; set; }

public virtual ICollection<Student> Students { get; set; }

}

در مثال بالا انتیتی فریم ورک، student1 را از دیتابیس حذف کرده و همچنین مقدار ستون standard_StandardId که به عنوان کلید خارجی در جدول Students تعریف شده است را به null تنظیم می‌کند. این موضوع برای تمامی رکوردهایی که به student1 ارجاع داده اند اتفاق می‌افتد. نکته بسیار مهم دیگر در رابطه با رابطه های many-to-many که دارای یک joining table می‌باشند است. در این سناریو نیز اگر یکی از entity ها حذف شود، رکورد مربوط به رابطه آنها از درون joining table حذف خواهد شد. تا به اینجای کار دانستیم که Entity Framework به طور پیش‌فرض cascade delete را برای تمامی رابطه ها و تمامی entity ها فعال می‌کند؛ اما شاید گاهی بخواهیم این موضوع را غیر فعال کنیم.

غیر فعال کردن Cascade Delete

با استفاده از Fluent API می توانیم entity را طوری پیکربندی کنیم که cascade delete برای آنها لحاظ نشود. این موضوع با استفاده از یک متد با نام WillCascadeOnDelete اتفاق می‌افتد. کد زیر این موضوع را نشان می‌دهد.

public class SchoolContext<: DbContext

{

public SchoolContext():base("MySchool")

{

}

public DbSet<Student> Students { get; set; }

public DbSet<Standard> Standards { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

modelBuilder.Entity<Student>()

.HasOptional<Standard>(s => s.Standard)

.WithMany()

.WillCascadeOnDelete(false);

}

}

نکته آخر اینکه برای غیرفعال کردن cascade delete در Entity Framework هیچ data annotation attribute خاصی وجود ندارد و این پیکربندی حتماً می بایستی که با استفاده کردن از Fluent API لحاظ بشود.

منبع:وبسایت پرووید