М'яке видалення (англ. Soft Delete) — шаблон проєктування, при якому сутність не видаляється зі сховища, а лише помічається як видалена.

Переваги та недоліки ред.

Переваги ред.

  • Дані ніколи не втрачаються оскільки нічого не видаляється.
  • Операція видалення працює швидше.
  • Запобігає випадковому видаленню даних.

Недоліки ред.

  • Зростає розмір сховища.
  • Всі запити містять додатковий фільтр, який варто підтримувати.

Реалізація ред.

Нехай, ми створюємо систему обліку даних. Тоді важливо, щоб усі звіти зберігались у системі, навіть після видалення. Додамо властивість, яка відстежує видалення.

public interface ISoftDeleted
{
    bool IsDeleted { get; }
    DateTime DeletedAt { get; }
    
    void Delete()
    {
        IsDeleted = true;
        DeletedAt = DateTime.Now;
    }
}

public class Report : ISoftDeleted
{
    public bool IsDeleted { get; private set; }
    public DateTime DeletedAt { get; private set; }
    
    public int Id { get; set; }
    public string Description { get; set; } 
}

Та додамо до усіх запитів перевірку на те чи сутність видалена.

public class ApplicationContext : DbContext
{
    public DbSet<Report> Reports { get; set; }
     
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Report>().HasQueryFilter(r => r.IsDeleted == false);
    }
}

При використанні доступні лише "не видалені" сутності.

using (ApplicationContext db = new ApplicationContext())
{  
     var report1 = new Report();
     var report2 = new Report();
     
     report2.Delete();
     
     db.Reports.AddRange(report1, report2);
     db.SaveChanges();
     
     foreach (var report in db.Reports.ToArray())
     {
         Console.WriteLine(report.Id);
     }
}

Також щоб не змінювати код, можна додати тригер, який замінить операцію видалення:

USE prods
GO
CREATE TRIGGER products_delete
ON Products
INSTEAD OF DELETE
AS
UPDATE Products
SET IsDeleted = 1
WHERE ID =(SELECT Id FROM deleted)

Джерела ред.