Soft Delete Pattern¶
Entities are marked as deleted instead of being physically removed.
Overview¶
stateDiagram-v2
[*] --> Active: Create
Active --> Active: Update
Active --> Deleted: Soft Delete
Deleted --> Active: Restore
Deleted --> [*]: Cleanup Job Soft delete preserves data for: - Audit trails - Undo functionality - Data recovery - Referential integrity
Implementation¶
Interface¶
public interface ISoftDeletable
{
bool IsDeleted { get; set; }
DateTime? DeletedDate { get; set; }
}
Entity¶
public class Marker : AuditableEntity, ISoftDeletable
{
public Guid MarkerId { get; set; }
public string Title { get; set; }
// ISoftDeletable
public bool IsDeleted { get; set; }
public DateTime? DeletedDate { get; set; }
}
Automatic Handling¶
SaveChangesAsync intercepts deletes and converts to soft delete:
// In DataContext.SaveChangesAsync
foreach (var entry in ChangeTracker.Entries<ISoftDeletable>())
{
if (entry.State == EntityState.Deleted)
{
entry.State = EntityState.Modified;
entry.Entity.IsDeleted = true;
entry.Entity.DeletedDate = dateTimeProvider.UtcNow;
}
}
Querying¶
Exclude Deleted (Default)¶
Include Deleted¶
Restoring¶
Entities Using Soft Delete¶
| Entity | Soft Delete |
|---|---|
| Group | Yes |
| Marker | Yes |
| Note | Yes |
| NoteItem | Yes |
| Transaction | Yes |
| RecurringTransaction | Yes |
| Category | Yes |
| BudgetAccount | Yes |
| User | No |
| StoredFile | No |
| AppTask | No |
Related¶
- Data Model — Entity relationships
- Concurrency — Optimistic locking