Soft deletion feature is important in some cases that you need a second step to delete the data in your database. When you first delete it from your C# LinQ query, the data will only be marked as Deleted but not delete in your database.

Multi-tenancy is one of the ASP.NET boilerplate's important features. But how can we implement the soft-deletion feature with only pure Entity Framework Core?

First, create an example entity like this:

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public bool IsDeleted { get; set; }
}

The Id of the post will be your primary key in your database. And the IsDeleted is for if the item is treated as a deleted item. Deleted items will not be selected. But you can still see it if your write SQL manually.

Create your DBContext like this:

public class BloggingContext : DbContext
{

    public BloggingContext()
    {

    }

    public DbSet<Post> Posts { get; set; }
}

To configure your SQL Server connection, override the default OnConfiguring like this:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=Demo.QueryFilters;Trusted_Connection=True;ConnectRetryCount=0;");
}

When the developer is trying to select blogs from the DBContext, we need to add a filter to get only blogs not deleted. Override the default OnModelCreating method.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Post>().HasQueryFilter(p => !p.IsDeleted);
}

If the developer is deleting an item from the table, we need to help him set the IsDeleted and prevent deleting it in the database.

public override int SaveChanges()
{
    ChangeTracker.DetectChanges();
    foreach (var item in ChangeTracker.Entries<Post>().Where(e => e.State == EntityState.Deleted))
    {
        item.State = EntityState.Modified;
        item.CurrentValues["IsDeleted"] = true;
    }
    return base.SaveChanges();
}

Now we have a soft-deletion DBContext. With a BloggingContext, developers can keep writing LINQ or lambda expression like he previously did and desn' need to concern about the deletion context for our context can handle entity deletion automatically.

With soft-deletion enabled, your data will never be dropped. So there might be more and more data in your database as time goes on. So you'd better configure another service to do the backup and deletion job.

And with soft-deletion, the cascaded deletion may stop working because the rules work on the database side. You have to manually delete cascaded entities.