درواقع که منظور از Cascade delete و یا حذف شدن آبشاری این است که در زمان حذف شدن یک رکورد، تمامی رکوردهای مرتبط با آن که اصطلاحاً به آنها dependent record نیز میگویند حذف شود. به طور پیش فرض در Entity Framework برای تمامی رابطه هایی که وجود دارند چه از نوع one-to-one باشد و چه از نوع one-to-many و یا many-to-many بحث مربوط به cascade delete فعال شده است.
در قسمت های قبلی با کلاس های 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 در 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 ها فعال میکند؛ اما شاید گاهی بخواهیم این موضوع را غیر فعال کنیم.
با استفاده از 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 لحاظ بشود.
منبع:وبسایت پرووید