Skip to content

Instantly share code, notes, and snippets.

@ebicoglu
Last active February 2, 2023 19:17
Show Gist options
  • Save ebicoglu/82723d502c3bddcb70b3b77ea567c22e to your computer and use it in GitHub Desktop.
Save ebicoglu/82723d502c3bddcb70b3b77ea567c22e to your computer and use it in GitHub Desktop.
New migration handler that came in v4.3.0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace Acme.BookStore.Data
{
public class MyProjectNameTenantDatabaseMigrationHandler :
IDistributedEventHandler<TenantCreatedEto>,
IDistributedEventHandler<TenantConnectionStringUpdatedEto>,
IDistributedEventHandler<ApplyDatabaseMigrationsEto>,
ITransientDependency
{
private readonly IEnumerable<IMyProjectNameDbSchemaMigrator> _dbSchemaMigrators;
private readonly ICurrentTenant _currentTenant;
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IDataSeeder _dataSeeder;
private readonly ITenantStore _tenantStore;
private readonly ILogger<MyProjectNameTenantDatabaseMigrationHandler> _logger;
public MyProjectNameTenantDatabaseMigrationHandler(
IEnumerable<IMyProjectNameDbSchemaMigrator> dbSchemaMigrators,
ICurrentTenant currentTenant,
IUnitOfWorkManager unitOfWorkManager,
IDataSeeder dataSeeder,
ITenantStore tenantStore,
ILogger<MyProjectNameTenantDatabaseMigrationHandler> logger)
{
_dbSchemaMigrators = dbSchemaMigrators;
_currentTenant = currentTenant;
_unitOfWorkManager = unitOfWorkManager;
_dataSeeder = dataSeeder;
_tenantStore = tenantStore;
_logger = logger;
}
public async Task HandleEventAsync(TenantCreatedEto eventData)
{
await MigrateAndSeedForTenantAsync(
eventData.Id,
eventData.Properties.GetOrDefault("AdminEmail") ?? MyProjectNameConsts.AdminEmailDefaultValue,
eventData.Properties.GetOrDefault("AdminPassword") ?? MyProjectNameConsts.AdminPasswordDefaultValue
);
}
public async Task HandleEventAsync(TenantConnectionStringUpdatedEto eventData)
{
if (eventData.ConnectionStringName != ConnectionStrings.DefaultConnectionStringName ||
eventData.NewValue.IsNullOrWhiteSpace())
{
return;
}
await MigrateAndSeedForTenantAsync(
eventData.Id,
MyProjectNameConsts.AdminEmailDefaultValue,
MyProjectNameConsts.AdminPasswordDefaultValue
);
/* You may want to move your data from the old database to the new database!
* It is up to you. If you don't make it, new database will be empty
* (and tenant's admin password is reset to 1q2w3E*).
*/
}
public async Task HandleEventAsync(ApplyDatabaseMigrationsEto eventData)
{
if (eventData.TenantId == null)
{
return;
}
await MigrateAndSeedForTenantAsync(
eventData.TenantId.Value,
MyProjectNameConsts.AdminEmailDefaultValue,
MyProjectNameConsts.AdminPasswordDefaultValue
);
}
private async Task MigrateAndSeedForTenantAsync(
Guid tenantId,
string adminEmail,
string adminPassword)
{
try
{
using (_currentTenant.Change(tenantId))
{
// Create database tables if needed
using (var uow = _unitOfWorkManager.Begin(requiresNew: false, isTransactional: false))
{
var tenantConfiguration = await _tenantStore.FindAsync(tenantId);
if (tenantConfiguration?.ConnectionStrings != null &&
!tenantConfiguration.ConnectionStrings.Default.IsNullOrWhiteSpace())
{
foreach (var migrator in _dbSchemaMigrators)
{
await migrator.MigrateAsync();
}
}
await uow.CompleteAsync();
}
// Seed data
using (var uow = _unitOfWorkManager.Begin(requiresNew: false, isTransactional: true))
{
await _dataSeeder.SeedAsync(
new DataSeedContext(tenantId)
.WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, adminEmail)
.WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, adminPassword)
);
await uow.CompleteAsync();
}
}
}
catch (Exception ex)
{
_logger.LogException(ex);
}
}
}
}
@ebicoglu
Copy link
Author

You need to put this class into /aspnet-core/src/Acme.BookStore/Domain/Data/ directory.

@pdave57
Copy link

pdave57 commented Feb 2, 2023

I don't know whether this solution work for anybody, I'm new in abp angular and the create tenant modal form save button is even disabled. How will I go around it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment