Last active
April 17, 2018 07:19
-
-
Save ebicoglu/6fe14f65a21713f673ba5b55e94bb682 to your computer and use it in GitHub Desktop.
[AspNet Zero] Drop tenant database when a tenant is deleted (for db for tenant usage)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using System.Linq; | |
using System.Linq.Dynamic.Core; | |
using System.Threading.Tasks; | |
using Abp; | |
using Abp.Application.Features; | |
using Abp.Application.Services.Dto; | |
using Abp.Authorization; | |
using Abp.Authorization.Users; | |
using Abp.Data; | |
using Abp.Domain.Uow; | |
using Abp.EntityFrameworkCore; | |
using Abp.Extensions; | |
using Abp.Linq.Extensions; | |
using Abp.MultiTenancy; | |
using Abp.Runtime.Security; | |
using Microsoft.EntityFrameworkCore; | |
using MyCompanyName.AbpZeroTemplate.Authorization; | |
using MyCompanyName.AbpZeroTemplate.Editions.Dto; | |
using MyCompanyName.AbpZeroTemplate.EntityFrameworkCore; | |
using MyCompanyName.AbpZeroTemplate.MultiTenancy.Dto; | |
using MyCompanyName.AbpZeroTemplate.Url; | |
namespace MyCompanyName.AbpZeroTemplate.MultiTenancy | |
{ | |
[AbpAuthorize(AppPermissions.Pages_Tenants)] | |
public class TenantAppService : AbpZeroTemplateAppServiceBase, ITenantAppService | |
{ | |
public IAppUrlService AppUrlService { get; set; } | |
private readonly IDbContextResolver _dbContextResolver; | |
private readonly IDbPerTenantConnectionStringResolver _connectionStringResolver; | |
public TenantAppService(IDbContextResolver dbContextResolver, | |
IDbPerTenantConnectionStringResolver connectionStringResolver) | |
{ | |
_dbContextResolver = dbContextResolver; | |
_connectionStringResolver = connectionStringResolver; | |
AppUrlService = NullAppUrlService.Instance; | |
} | |
public async Task<PagedResultDto<TenantListDto>> GetTenants(GetTenantsInput input) | |
{ | |
var query = TenantManager.Tenants | |
.Include(t => t.Edition) | |
.WhereIf(!input.Filter.IsNullOrWhiteSpace(), t => t.Name.Contains(input.Filter) || t.TenancyName.Contains(input.Filter)) | |
.WhereIf(input.CreationDateStart.HasValue, t => t.CreationTime >= input.CreationDateStart.Value) | |
.WhereIf(input.CreationDateEnd.HasValue, t => t.CreationTime <= input.CreationDateEnd.Value) | |
.WhereIf(input.SubscriptionEndDateStart.HasValue, t => t.SubscriptionEndDateUtc >= input.SubscriptionEndDateStart.Value.ToUniversalTime()) | |
.WhereIf(input.SubscriptionEndDateEnd.HasValue, t => t.SubscriptionEndDateUtc <= input.SubscriptionEndDateEnd.Value.ToUniversalTime()) | |
.WhereIf(input.EditionIdSpecified, t => t.EditionId == input.EditionId); | |
var tenantCount = await query.CountAsync(); | |
var tenants = await query.OrderBy(input.Sorting).PageBy(input).ToListAsync(); | |
return new PagedResultDto<TenantListDto>( | |
tenantCount, | |
ObjectMapper.Map<List<TenantListDto>>(tenants) | |
); | |
} | |
[AbpAuthorize(AppPermissions.Pages_Tenants_Create)] | |
[UnitOfWork(IsDisabled = true)] | |
public async Task CreateTenant(CreateTenantInput input) | |
{ | |
await TenantManager.CreateWithAdminUserAsync(input.TenancyName, | |
input.Name, | |
input.AdminPassword, | |
input.AdminEmailAddress, | |
input.ConnectionString, | |
input.IsActive, | |
input.EditionId, | |
input.ShouldChangePasswordOnNextLogin, | |
input.SendActivationEmail, | |
input.SubscriptionEndDateUtc?.ToUniversalTime(), | |
input.IsInTrialPeriod, | |
AppUrlService.CreateEmailActivationUrlFormat(input.TenancyName) | |
); | |
} | |
[AbpAuthorize(AppPermissions.Pages_Tenants_Edit)] | |
public async Task<TenantEditDto> GetTenantForEdit(EntityDto input) | |
{ | |
var tenantEditDto = ObjectMapper.Map<TenantEditDto>(await TenantManager.GetByIdAsync(input.Id)); | |
tenantEditDto.ConnectionString = SimpleStringCipher.Instance.Decrypt(tenantEditDto.ConnectionString); | |
return tenantEditDto; | |
} | |
[AbpAuthorize(AppPermissions.Pages_Tenants_Edit)] | |
public async Task UpdateTenant(TenantEditDto input) | |
{ | |
await TenantManager.CheckEditionAsync(input.EditionId, input.IsInTrialPeriod); | |
input.ConnectionString = SimpleStringCipher.Instance.Encrypt(input.ConnectionString); | |
var tenant = await TenantManager.GetByIdAsync(input.Id); | |
ObjectMapper.Map(input, tenant); | |
tenant.SubscriptionEndDateUtc = tenant.SubscriptionEndDateUtc?.ToUniversalTime(); | |
await TenantManager.UpdateAsync(tenant); | |
} | |
[AbpAuthorize(AppPermissions.Pages_Tenants_Delete)] | |
public async Task DeleteTenant(EntityDto input) | |
{ | |
var tenant = await TenantManager.GetByIdAsync(input.Id); | |
await TenantManager.DeleteAsync(tenant); | |
await DropTenantDatabase(tenant); | |
} | |
private async Task DropTenantDatabase(AbpTenantBase tenant) | |
{ | |
var args = new DbPerTenantConnectionStringResolveArgs(tenant.Id, MultiTenancySides.Tenant) | |
{ | |
["DbContextType"] = typeof(AbpZeroTemplateDbContext), | |
["DbContextConcreteType"] = typeof(AbpZeroTemplateDbContext) | |
}; | |
var connectionString = ConnectionStringHelper.GetConnectionString( | |
_connectionStringResolver.GetNameOrConnectionString(args) | |
); | |
using (var dbContext = _dbContextResolver.Resolve<AbpZeroTemplateDbContext>(connectionString, null)) | |
{ | |
await dbContext.Database.EnsureDeletedAsync(); | |
} | |
} | |
[AbpAuthorize(AppPermissions.Pages_Tenants_ChangeFeatures)] | |
public async Task<GetTenantFeaturesEditOutput> GetTenantFeaturesForEdit(EntityDto input) | |
{ | |
var features = FeatureManager.GetAll() | |
.Where(f => f.Scope.HasFlag(FeatureScopes.Tenant)); | |
var featureValues = await TenantManager.GetFeatureValuesAsync(input.Id); | |
return new GetTenantFeaturesEditOutput | |
{ | |
Features = ObjectMapper.Map<List<FlatFeatureDto>>(features).OrderBy(f => f.DisplayName).ToList(), | |
FeatureValues = featureValues.Select(fv => new NameValueDto(fv)).ToList() | |
}; | |
} | |
[AbpAuthorize(AppPermissions.Pages_Tenants_ChangeFeatures)] | |
public async Task UpdateTenantFeatures(UpdateTenantFeaturesInput input) | |
{ | |
await TenantManager.SetFeatureValuesAsync(input.Id, input.FeatureValues.Select(fv => new NameValue(fv.Name, fv.Value)).ToArray()); | |
} | |
[AbpAuthorize(AppPermissions.Pages_Tenants_ChangeFeatures)] | |
public async Task ResetTenantSpecificFeatures(EntityDto input) | |
{ | |
await TenantManager.ResetAllFeaturesAsync(input.Id); | |
} | |
public async Task UnlockTenantAdmin(EntityDto input) | |
{ | |
using (CurrentUnitOfWork.SetTenantId(input.Id)) | |
{ | |
var tenantAdmin = await UserManager.FindByNameAsync(AbpUserBase.AdminUserName); | |
if (tenantAdmin != null) | |
{ | |
tenantAdmin.Unlock(); | |
} | |
} | |
} | |
} | |
} |
This is the code that's deleting a database in Entity Framework
private async Task DropTenantDatabase(AbpTenantBase tenant)
{
var args = new DbPerTenantConnectionStringResolveArgs(tenant.Id, MultiTenancySides.Tenant)
{
["DbContextType"] = typeof(AbpZeroTemplateDbContext),
["DbContextConcreteType"] = typeof(AbpZeroTemplateDbContext)
};
var connectionString = ConnectionStringHelper.GetConnectionString(
_connectionStringResolver.GetNameOrConnectionString(args)
);
using (var dbContext = _dbContextResolver.Resolve<AbpZeroTemplateDbContext>(connectionString, null))
{
await dbContext.Database.EnsureDeletedAsync();
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Drop the database right after the tenant is being deleted in TenantAppService.cs > DeleteTenant() method.