Base solution for your next web application
Open Closed

Cascade deletion not working? #4021


User avatar
0
DennisAhlin created

Hi! I have an integration entity, which have many integration step entities. The steps also have links to other steps in the same integration.

Like

Integration1 || \ Step1 = Step2

I can not figure out how to get the cascade deletion working when I delete an integration? The integration is deleted, but not the integration steps. How can I solve this?


6 Answer(s)
  • User Avatar
    0
    aaron created
    Support Team

    Are those entities soft-deleted? If so, you need to cascade soft deletes yourself.

  • User Avatar
    0
    DennisAhlin created

    The integration entity gets soft deleted, but not the steps (they are untouched). Aren't cascading of soft deletion implemented in Boilerplate?

  • User Avatar
    0
    aaron created
    Support Team

    Nope. AFAIK there's no direct way to discover cascade relationships. Also, the purpose of cascading is for data integrity when hard-deleting. Since soft-deleted data is still there, not everyone may want to cascade that delete. So it's more reasonable to do this explicitly. Related issue: https://github.com/aspnetboilerplate/aspnetboilerplate/issues/1992

  • User Avatar
    0
    DennisAhlin created

    So, basically I have to do this:

    public class MyDbContext : AbpZeroDbContext<Tenant, Role, User, MyDbContext>, IAbpPersistedGrantDbContext
    {
         ...
        public override int SaveChanges()
        {
            var deletedIntegrations = ChangeTracker.Entries<Integration>()
                .Where(j => j.State == EntityState.Deleted)
                .Select(e => e.Entity)
                .ToArray();
    
            foreach (var deletedIntegration in deletedIntegrations)
            {
                IntegrationSteps.Remove(e => e.IntegrationId == deletedIntegration.Id);
            }
    
            return base.SaveChanges();
        }
    }
    

    Any suggestions on how to do this more maintainable?

  • User Avatar
    0
    aaron created
    Support Team

    Define an event handler:

    public class IntegrationDeletingCascader : IEventHandler<EntityDeletingEventData<Integration>>, ITransientDependency
    {
        private readonly IRepository<IntegrationStep> _integrationStepRepository;
    
        public IntegrationDeletingCascader(IRepository<IntegrationStep> integrationStepRepository)
        {
            _integrationStepRepository = integrationStepRepository;
        }
    
        [UnitOfWork]
        public virtual void HandleEvent(EntityDeletingEventData<Integration> eventData)
        {
            var deletedIntegration = eventData.Entity;
            _integrationStepRepository.Delete(e => e.IntegrationId == deletedIntegration.Id);
        }
    }
    
  • User Avatar
    0
    DennisAhlin created

    Ah, nice! Thank you for your help! :)