Soft Delete
Soft delete allows entities to be logically removed without deleting the database row. Deleted entities are hidden from queries by default and can be restored or audited later.
Overview
Implement ISoftDeletable on any entity to opt in to soft-delete behavior:
public class Article : ISoftDeletable
{
public Guid Id { get; set; }
public string Title { get; set; } = "";
public bool IsDeleted { get; set; }
public DateTime? DeletedAt { get; set; }
}
When a DELETE /articles/{id} request is received:
- MapCrud sets
IsDeleted = trueandDeletedAt = DateTime.UtcNow - No row is removed from the database
- The operation is idempotent: deleting an already-soft-deleted entity returns 204 No Content
Filtering
Soft-deleted entities are automatically excluded from GET responses unless the client requests them:
GET /articles # returns only non-deleted articles
GET /articles?includeDeleted=true # returns all articles including soft-deleted
GET /articles/{id} # returns 404 if the article is soft-deleted
GET /articles/{id}?includeDeleted=true # returns the article even if soft-deleted
EF Core Setup
Call ApplySoftDeleteFilters() in OnModelCreating to register global query filters automatically for all ISoftDeletable entities:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplySoftDeleteFilters();
// ...
}
This registers an EF Core global query filter WHERE IsDeleted = 0 on every entity type that implements ISoftDeletable. The filter is bypassed when IgnoreQueryFilters() is applied (which happens automatically inside EfRepository when includeDeleted=true).
In-Memory Setup
The InMemoryRepository applies soft-delete filtering in-process. No additional configuration is needed.
Hard Delete
For entities that do not implement ISoftDeletable, the DELETE endpoint performs a hard delete
(removes the row/entry permanently).
Related Features
- Operation Configuration — Disable the DELETE endpoint entirely with
.DisableDelete() - Getting Started — Basic setup