در آموزش OnDelete در EF Core قصد داریم یکی از مفاهیم مهم در طراحی پایگاه داده با استفاده از Entity Framework Core را بررسی کنیم. Delete Behavior یا همان OnDelete. هنگامی که بین دو Entity رابطه برقرار میکنیم، باید تعیین کنیم که هنگام حذف یکی از طرفین، چه اتفاقی برای طرف دیگر بیفتد. این رفتارها با استفاده از متد .OnDelete() در Fluent API قابل تنظیم هستند.
در EF Core، پنج روش اصلی برای تعیین رفتار حذف وجود دارد: در این آموزش، تمرکز ما روی سه نوع پرکاربرد یعنی Cascade، Restrict و SetNull خواهد بود.
| نوع | توضیح عملکرد | مثال کاربردی |
|---|---|---|
| Cascade | با حذف موجودیت والد، موجودیتهای فرزند نیز بهصورت خودکار حذف میشوند. | حذف سفارشات هنگام حذف مشتری |
| Restrict | اگر موجودیت فرزند وجود داشته باشد، حذف والد مجاز نیست. خطای ReferentialIntegrityException دریافت میشود. | جلوگیری از حذف دستهبندی که محصول دارد |
| SetNull | هنگام حذف والد، کلید خارجی فرزند null میشود (در صورت nullable بودن FK). | حذف مدیر، اما نگهداشتن پروژه بدون مدیر |
در این مثال، اگر یک شرکت حذف شود، کلید خارجی کارمندان آن به null تبدیل میشود.
modelBuilder.Entity<Company>()
.HasMany(c => c.Employees)
.WithOne(e => e.Company)
.HasForeignKey(e => e.CompanyId)
.OnDelete(DeleteBehavior.SetNull);
بر خلاف سایر تنظیمات مانند [Required] یا [MaxLength]، رفتار حذف (OnDelete) فقط با Fluent API قابل کنترل است و از طریق Data Annotation امکانپذیر نیست.
پس از اجرای دستور Add-Migration. در فایل migration کدی مشابه زیر مشاهده میشود. و در دیتابیس، Foreign Key با رفتار حذف تعیینشده ایجاد خواهد شد.
onDelete: ReferentialAction.SetNull
حذف در زمان حذف موجودیتها با رفتار Restrict یا در شرایط همزمانی، باید با استفاده از try-catch خطاها مدیریت شوند.
try
{
_context.Companies.Remove(company);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
TempData["Error"] = "خطای همزمانی رخ داده است. لطفاً دوباره تلاش کنید.";
}
catch (DbUpdateException ex)
{
if (ex.InnerException?.Message.Contains("REFERENCE constraint") == true)
TempData["Error"] = "امکان حذف این شرکت وجود ندارد چون به آن کارمند اختصاص داده شده است.";
else
TempData["Error"] = "خطایی هنگام ذخیره اطلاعات رخ داد. لطفاً دوباره تلاش کنید.";
}
catch (Exception ex)
{
TempData["Error"] = "خطای ناشناختهای رخ داده است: " + ex.Message;
}
درک و تنظیم صحیح رفتار حذف، نقش کلیدی در امنیت و پایداری دادهها دارد. با استفاده درست از آنها میتوان از بروز بسیاری از خطاهای منطقی و امنیتی جلوگیری کرد.