Entity Framework Classic Soft Delete

Description

The Soft Delete feature allows you to flag entities as deleted (Soft Delete) instead of deleting them physically (Hard Delete).

public class SoftDeleteEntitiesContext : DbContext
{
    public SoftDeleteEntitiesContext() : base("EntitiesContext")
    {
        this.Configuration.SoftDelete.Trigger<SoftDeleteEntity>((context, delete) =>{delete.IsDeleted = false;});
    }
    public DbSet<SoftDeleteEntity> SoftDeleteEntities { get; set; }
}

Try it: NET Framework | NET Core

The soft delete feature can be achieved by using the 'IEFSoftDelete' interface. By default, this interface is always added to the manager. Otherwise, you can add your own interface and trigger action to perform a soft delete.

The IEFSoftDelete interface will handle any entities that have a column named 'IsDeleted' with the boolean type. Any entity that inherits this interface will be soft-deleted instead of being completely deleted when saving changes from a context.

Advantage

  • Centralize logic in a single interface to handle the soft delete
  • Reduce the chance of missing a soft delete when introducing a new entity
  • Improve development productivity

Getting Started

Default Interface

You can use the default soft delete by inheriting the 'IEFSoftDelete' interface.

public class SoftDeleteEntity : IEFSoftDelete
{
    public int SoftDeleteEntityID { get; set; }
    public int ColumnInt { get; set; }
    public string ColumnString { get; set; }
    public bool IsDeleted { get; set; }
    public bool AutoDelete { get; set; }
}

Try it: NET Core | NET Framework

Custom Interface

You can create a custom soft delete trigger by adding it to the manager

public class EntityContext : DbContext
{
    public EntityContext() : base(FiddleHelper.GetConnectionStringSqlServer())
    {
        this.Configuration.SoftDelete.Trigger<ICustomeSoftDelete>((context, customer) =>            
        {
            customer.isActive = false;
            customer.DeletedAt = DateTime.UtcNow;                            
        });
    }
        
    public DbSet<Customer> Customers { get; set; }
}

Try it: NET Core | NET Framework

Enable/Disable Soft Delete Trigger

You can enable/disable all existing soft delete triggers by using IsEnabled on the manager or individual trigger and use it with the EnableTrigger(T) and DisableTrigger(T) methods.

using (var context = new EntityContext())
{
    context.Configuration.SoftDelete.DisableTrigger<IEFSoftDelete>();  
        
    // Delete A from Customers as A where Name = 'Customer_A'
    var list = context.Customers.Where(x => x.Name == "Customer_A").ToList();
    context.Customers.RemoveRange(list);
    context.SaveChanges();    
            
    FiddleHelper.WriteTable("After Delete With DisableTrigger", context.Customers.ToList());        
            
    context.Configuration.SoftDelete.EnableTrigger<IEFSoftDelete>();  
            
    context.Customers.RemoveRange(context.Customers.ToList());
    context.SaveChanges();    
}

Try it: NET Core | NET Framework

Real-Life Scenarios

Soft Delete

Your application uses Soft Delete/Logical Delete to delete entities.

The Soft Delete allows you to mark entities as deleted instead of physically deleting them.

public class EntityContext : DbContext
{
    public EntityContext() : base(FiddleHelper.GetConnectionStringSqlServer())
    {
        this.Configuration.SoftDelete.Trigger<ICustomSoftDelete>((context, customer) =>                                {
            customer.isActive = false;
            customer.DeletedAt = DateTime.UtcNow;
        });
    }
        
    public DbSet<Customer> Customers { get; set; }
        
    public class Customer : ICustomSoftDelete
    {
        public int CustomerID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public bool isActive { get; set; }
        public DateTime? DeletedAt   { get; set; }
    }
    
    public interface ICustomSoftDelete
    {
        bool isActive  { get; set; }
        DateTime? DeletedAt   { get; set; }
    }
}

Try it: NET Core | NET Framework

Documentation

SoftDeleteTrigger

Properties
Name Description Example
EntityType Gets the SofDeleteTrigger entity type. NET Core / NET Framework
IsEnabled Gets if the SofDeleteTrigger is enabled. Use Enable() and Disable() method to change the state. Always return false if the SoftDeleteTrigger feature is disabled. NET Core / NET Framework
Methods
Name Description Example
Enable() Enable the SoftDeleteTrigger. NET Core / NET Framework
Disable() Disable the SoftDeleteTrigger. NET Core / NET Framework

SoftDeleteManager

Properties
Name Description Example
IsEnabled Gets or sets if the Soft Delete feature is enabled. NET Core / NET Framework
Methods
Name Description Example
Trigger<TEntityType>(Action<DbContext, TEntityType> action) Execute an action when an entity type state is set to Deleted and set the state to modified afterward NET Core / NET Framework
EnableTrigger<TEntityType>() Enable the SoftDeleteTrigger with the specified id. NET Core / NET Framework
DisableTrigger<TEntityType>() Disable the SoftDeleteTrigger with the specified id. NET Core / NET Framework
Triggers() Get a list of SoftDeleteTrigger. NET Core / NET Framework
GetTrigger<TEntityType>() Get the SoftDeleteTrigger with the specified id. NET Core / NET Framework

Limitations

There can be only one trigger by entity type. If a second trigger tries to be added an exception will be raised.

The SoftDeleteFeature is not supported by the BulkSynchronize operation.


Contents