3

I'm developing a multitenant application and would like to have to option to remove a tenant. This however seems to be less trivial than one would assume.

My goal is to delete all references to the tenant everywhere in the database. I understand that Tenant is Soft-Delete, but I since I don't want my database to fill up with old meaningless data I've tried disabling the soft-delete filter.

Here is some code that I've tried:

using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete))
{
    await TenantRepository.DeleteAsync(x => x.Id == tenantId);
}

This did not work. The tenant is marked as "IsDeleted" but not removed. Then I figured that maybe it has something to do with UnitOfWork so I made sure no UnitOfWork was active and then manually controlled it:

using (var unitOfWork = _unitOfWorkManager.Begin())
{
    // the codeblock above went here
    unitOfWork.Complete();
}

This did not work, same result. And this is just the AbpTenant table. I'm also trying to delete from all other tables. For example AbpSettings and AbpLanguages. It's very unclear to me how to do that at all - the "managers" doesn't contain any Delete functions.

I tried creating IRepository for these entities but it does not work. The error reads

The type Abo.Configuration.Setting cannot be used as a type parameter TEntity in the generic type or method IRepository. There is no implicit reference conversion from Abp.Configuration.Setting to Abo.Domain.Entities.IEntity.

That leaves me with the option to use the DataContext directly:

using (EntityFramework.MyDbContext db = new  EntityFramework.MyDbContext())
{
    List<PermissionSetting> perms = await db.Permissions.Where(x => x.TenantId == tenantId).ToListAsync();

    for (int i=0; i<perms.Count(); i++)
    {
        db.Permissions.Remove(perms[i]);
    }

    // I also tried deleting them in bulk at first 
    // ((DbSet<PermissionSetting>)db.Permissions).RemoveRange(db.Permissions.Where(x => x.TenantId == tenantId));

    await db.SaveChangesAsync();
}

I tried that with and without UnitOfWork.

But it simply does not get deleted from the database. I'm getting no errors or Exceptions.

Why does it not get deleted? How can I delete it? Surely it must be possible?

Niklas Jonsson
  • 173
  • 2
  • 8

1 Answers1

1

since I don't want my database to fill up with old meaningless data I've tried disabling the soft-delete filter.

From the question on Disable SoftDelete for AbpUserRole:

protected override void CancelDeletionForSoftDelete(EntityEntry entry)
{
    if (IsSoftDeleteFilterEnabled)
    {
        base.CancelDeletionForSoftDelete(entry);
    }
}

The type Abo.Configuration.Setting cannot be used as a type parameter TEntity in the generic type or method IRepository. There is no implicit reference conversion from Abp.Configuration.Setting to Abo.Domain.Entities.IEntity.

Inject IRepository<Setting, long> instead of IRepository<Setting>.

That leaves me with the option to use the DataContext directly ... But it simply does not get deleted from the database. I'm getting no errors or Exceptions.

From the documentation on Data Filters:

using (_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.MayHaveTenant))
{
    using (var db = new ...)
    {
        // ...
    }
}

That said, there is no way to easily delete related tenant data completely. Consider writing SQL.

aaron
  • 39,695
  • 6
  • 46
  • 102