We have solution that contains multiple microservices. One of them contains host entities and data others are tenant specific entity and services. We haave DbMigrator console app in our host project only. Now we are able to run DbMigrator as console app in development and migrate host and tenant database that is:
- Creates Host database
- Creates Tenant database with same Db Schema as Host with default Admin user
- For other services, We create database using Script Migration
How to run this DbMigrator in a Production server. Can we control DbMigrator to migrate all the databases we need to migrate? We see there is option to "Apply Database Migrations" in Saas module but it does not seem to work. What sort of implementation it requires?
- ABP Framework version: v4.3.1
- UI type: Angular
- DB provider: EF Core
- Tiered (MVC) or Identity Server Separated (Angular): yes
- Exception message and stack trace:
- Steps to reproduce the issue:"
3 Answer(s)
-
0
Hi
How to run this DbMigrator in a Production server.
DbMigrator project is a console application, you can directly use
dotnet
command to run it.Can we control DbMigrator to migrate all the databases we need to migrate?
Of course, in fact, the DbMigrator will call
MigrateAsync
method ofI<Project>DbSchemaMigrator
. you can create....DbSchemaMigrator
Implementation class for each service. -
0
Thanks a lot.
And also can you give some light on:
We see there is option to "Apply Database Migrations" in Saas module but it does not seem to work? How to enable or implement this feature?
-
0
We see there is option to "Apply Database Migrations" in Saas module but it does not seem to work?
Apply Database Migrations
will publish an event withApplyDatabaseMigrationsEto
.You can create an event handler to create the database. for example:
public class MyProjectNameTenantDatabaseMigrationHandler : 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(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: true, 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: true, 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); } } }