پیادهسازی حذف نرم (Soft Delete) با EF Core 💾
حذف کردن یا نکردن، مسئله این است. 🤔
روش سنتی برای حذف اطلاعات در پایگاه داده، از طریق "حذف سخت" (hard delete) است. یک حذف سخت، یک رکورد را برای همیشه از جدول پایگاه داده پاک میکند. اگرچه این روش ساده به نظر میرسد، اما ریسک قابل توجهی دارد: وقتی دادهای حذف شد، برای همیشه از بین رفته است. 💥
به جای حذف فیزیکی یک رکورد، در "حذف نرم" (soft delete) آن را به عنوان حذف شده علامتگذاری میکنیم، معمولاً با قرار دادن یک فلگ مانند IsDeleted به مقدار true. رکورد در پایگاه داده باقی میماند، اما به طور موثر از کوئریهای عادی برنامه پنهان میشود. 🛡️
امروز، به جزئیات نحوه پیادهسازی حذف نرم با استفاده از EF Core خواهیم پرداخت. در مورد فیلترهای کوئری سراسری بحث خواهیم کرد، روشهای کارآمد برای مدیریت دادههای حذف نرم شده را بررسی میکنیم و مزایا و معایب آن را میسنجیم. 🚀
حذف نرم (Soft Delete) چیست؟ 🧐
حذف نرم یک استراتژی پایداری داده است که از حذف دائمی رکوردها از پایگاه داده شما جلوگیری میکند. به جای حذف داده از پایگاه داده، یک فلگ روی رکورد تنظیم میشود که آن را به عنوان "حذف شده" مشخص میکند.
این رویکرد به برنامه اجازه میدهد تا در کوئریهای عادی این رکوردها را نادیده بگیرد. با این حال، در صورت لزوم میتوانید این رکوردها را بازیابی کنید. حذف نرم همچنین زمانی کاربردی است که بخواهید قیود کلید خارجی (foreign key constraints) را حفظ کنید. حذف نرم یک عملیات "غیرمخرب" است، در مقابل حذف سخت که در آن دادهها به طور کامل حذف میشوند. 🔄
یک حذف سخت از دستور DELETE در SQL استفاده میکند:
DELETE FROM bookings.Reviews
WHERE Id = @BookingId;
از طرف دیگر، یک حذف نرم از دستور UPDATE استفاده میکند:
UPDATE bookings.Reviews
SET IsDeleted = 1, DeletedOnUtc = @UtcNow
WHERE Id = @BookingId;
دادهها هنوز در پایگاه داده وجود دارند و این عملیات قابل بازگشت است.
اما باید به خاطر داشته باشید که هنگام کوئری گرفتن از پایگاه داده، دادههای حذف نرم شده را فیلتر کنید:
SELECT *
FROM bookings.Reviews
WHERE IsDeleted = 0;
بیایید ببینیم چگونه میتوانیم حذف نرم را با EF Core پیادهسازی کنیم. 👨💻
حذف نرم با استفاده از رهگیرها (Interceptors) در EF Core ⚙️
رهگیرهای EF Core یک مکانیزم قدرتمند برای رهگیری و تغییر عملیات پایگاه داده فراهم میکنند. به عنوان مثال، میتوانید عملیات ذخیره تغییرات (saving changes) را برای پیادهسازی قابلیت حذف نرم رهگیری کنید.
بیایید یک اینترفیس نشانگر ISoftDeletable برای نمایش موجودیتهای قابل حذف نرم ایجاد کنیم:
public interface ISoftDeletable
{
bool IsDeleted { get; set; }
DateTime? DeletedOnUtc { get; set; }
}
موجودیتهایی که باید از حذف نرم پشتیبانی کنند، این اینترفیس را پیادهسازی خواهند کرد. شما باید مایگریشن مربوطه را برای ایجاد این ستونها در پایگاه داده اعمال کنید.
مولفه بعدی که نیاز داریم یک SaveChangesInterceptor است که به ما اجازه میدهد به متد SavingChangesAsync (یا SavingChanges) متصل شویم. ما میتوانیم به ChangeTracker دسترسی پیدا کنیم و به دنبال ورودیهایی بگردیم که ISoftDeletable را پیادهسازی کرده و برای حذف شدن علامتگذاری شدهاند. این موضوع را میتوانیم با بررسی اینکه وضعیت موجودیت (entity state) برابر با EntityState.Deleted است، تشخیص دهیم.