Rohit Cdy
Posted on • Edited on
Implementing Soft Delete With EF Core.
What is soft delete?
Prevents permanent deletion of records.
Flag set on record, indicating "delete".
Allows for easy restoration and maintains data integrity.
How to implement:
- Create Marker Interface.
Define a marker interface ISoftDelete to mark entities that support soft delete.
public interface ISoftDelete{ bool IsDeleted { get; set; } DateTime? DeleteOnUtc { get; set; }}
- Implement Soft Delete Interceptor.
Create a class SoftDeleteInterceptor to handle soft deletes in EF Core.
public sealed class SoftDeleteInterceptor: SaveChangesInterceptor{ public override ValueTask<InterceptionResult<int>> SavingChangesAsync( DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default) { if (eventData.Context is null) { return base.SavingChangesAsync(eventData, result, cancellationToken); } IEnumerable<EntityEntry<ISoftDeletable>> entries = eventData.Context.ChangeTracker.Entries<ISoftDeletable>() .Where(e => e.State == EntityState.Deleted); foreach (EntityEntry<ISoftDeletable> softDeletable in entries) { softDeletable.State = EntityState.Modified; softDeletable.Entity.IsDeleted = true; softDeletable.Entity.DeletedOnUtc = DateTime.UtcNow; } return base.SavingChangesAsync(eventData, result, cancellationToken); }}
- Configure Application Context.
Configure EF Core to use the soft delete interceptor and global query filters.
public class ApplicationDbContext: DbContext{ public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public DbSet<User> Users { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // HasQueryFilter is used to filter soft-deleted data automatically. modelBuilder.Entity<User>().HasQueryFilter(r => !r.IsDeleted); modelBuilder.Entity<User>() .HasIndex(r=> r.IsDeleted) .HasFilter("IsDeleted=0"); // This HasFilter method accepts the SQL filter for records that will be included in the index. // You can also create a filtered index using SQL: /* Create index IX_Users_IsDeleted on User(IsDeleted) where IsDelete =0; */ }}
- Register SoftDeleteIntercepter with dependency injection.
services.AddSingleton<SoftDeleteInterceptor>();services.AddDbContext<ApplicationDbContext>( sp, options)=>options .UseSqlServer(connectionString) .AddInterceptor( sp.GetRequiredService<SoftDeleteInterceptor>()));
- Example Entity.
Create an example entity Review implementing the soft delete marker interface.
public class User: ISoftDeletable{ public int Id { get; set; } public string UserName { get; set; } public bool IsDeleted { get; set; } public DateTime? DeletedOnUtc { get; set; }}
Benefits:
- Flexibility in managing data.
- Simplified queries with automatic exclusion of soft-deleted records.
- Improved performance with filtered indexes.
Conclusion
- Soft delete ensures data integrity and flexibility in managing records without compromising performance.
Top comments(0)
Subscribe
For further actions, you may consider blocking this person and/orreporting abuse