@ -1,4 +1,4 @@
using System ;
using System ;
using System.Collections.Generic ;
using System.Diagnostics ;
using System.IO ;
@ -13,207 +13,208 @@ using Volo.Abp.Identity;
using Volo.Abp.MultiTenancy ;
using Volo.Abp.TenantManagement ;
namespace Lion.AbpPro.Data ;
public class AbpProDbMigrationService : ITransientDependency
namespace Lion.AbpPro.Data
{
public ILogger < AbpProDbMigrationService > Logger { get ; set ; }
private readonly IDataSeeder _d ataSeeder ;
private readonly IEnumerable < IAbpProDbSchemaMigrator > _d bSchemaMigrators ;
private readonly ITenantRepository _ tenantRepository ;
private readonly ICurrentTenant _ currentTenant ;
public AbpProDbMigrationService (
IDataSeeder dataSeeder ,
IEnumerable < IAbpProDbSchemaMigrator > dbSchemaMigrators ,
ITenantRepository tenantRepository ,
ICurrentTenant currentTenant )
public class AbpProDbMigrationService : ITransientDependency
{
_d ataSeeder = dataSeeder ;
_d bSchemaMigrators = dbSchemaMigrators ;
_ tenantRepository = tenantRepository ;
_ currentTenant = currentTenant ;
Logger = NullLogger < AbpProDbMigrationService > . Instance ;
}
public ILogger < AbpProDbMigrationService > Logger { get ; set ; }
private readonly IDataSeeder _d ataSeeder ;
private readonly IEnumerable < IAbpProDbSchemaMigrator > _d bSchemaMigrators ;
private readonly ITenantRepository _ tenantRepository ;
private readonly ICurrentTenant _ currentTenant ;
public AbpProDbMigrationService (
IDataSeeder dataSeeder ,
IEnumerable < IAbpProDbSchemaMigrator > dbSchemaMigrators ,
ITenantRepository tenantRepository ,
ICurrentTenant currentTenant )
{
_d ataSeeder = dataSeeder ;
_d bSchemaMigrators = dbSchemaMigrators ;
_ tenantRepository = tenantRepository ;
_ currentTenant = currentTenant ;
public async Task MigrateAsync ( )
{
var initialMigrationAdded = AddInitialMigrationIfNotExist ( ) ;
Logger = NullLogger < AbpProDbMigrationService > . Instance ;
}
if ( initialMigrationAdded )
public async Task MigrateAsync ( )
{
return ;
}
var initialMigrationAdded = AddInitialMigrationIfNotExist ( ) ;
Logger . LogInformation ( "Started database migrations..." ) ;
if ( initialMigrationAdded )
{
return ;
}
await MigrateDatabaseSchemaAsync ( ) ;
await SeedDataAsync ( ) ;
Logger . LogInformation ( "Started database migrations..." ) ;
Logger . LogInformation ( $"Successfully completed host database migrations." ) ;
await MigrateDatabaseSchemaAsync ( ) ;
await SeedDataAsync ( ) ;
var tenants = await _ tenantRepository . GetListAsync ( includeDetails : true ) ;
Logger . LogInformation ( $"Successfully completed host database migrations." ) ;
var migratedDatabaseSchemas = new HashSet < string > ( ) ;
foreach ( var tenant in tenants )
{
using ( _ currentTenant . Change ( tenant . Id ) )
var tenants = await _ tenantRepository . GetListAsync ( includeDetails : true ) ;
var migratedDatabaseSchemas = new HashSet < string > ( ) ;
foreach ( var tenant in tenants )
{
if ( tenant . ConnectionStrings . Any ( ) )
using ( _ currentTenant . Change ( tenant . Id ) )
{
var tenantConnectionStrings = tenant . ConnectionStrings
. Select ( x = > x . Value )
. ToList ( ) ;
if ( ! migratedDatabaseSchemas . IsSupersetOf ( tenantConnectionStrings ) )
if ( tenant . ConnectionStrings . Any ( ) )
{
await MigrateDatabaseSchemaAsync ( tenant ) ;
var tenantConnectionStrings = tenant . ConnectionStrings
. Select ( x = > x . Value )
. ToList ( ) ;
if ( ! migratedDatabaseSchemas . IsSupersetOf ( tenantConnectionStrings ) )
{
await MigrateDatabaseSchemaAsync ( tenant ) ;
migratedDatabaseSchemas . AddIfNotContains ( tenantConnectionStrings ) ;
migratedDatabaseSchemas . AddIfNotContains ( tenantConnectionStrings ) ;
}
}
await SeedDataAsync ( tenant ) ;
}
await SeedDataAsync ( tenant ) ;
Logger . LogInformation ( $"Successfully completed {tenant.Name} tenant database migrations." ) ;
}
Logger . LogInformation ( $"Successfully completed {tenant.Name} tenant database migrations." ) ;
Logger . LogInformation ( "Successfully completed all database migrations." ) ;
Logger . LogInformation ( "You can safely end this process..." ) ;
}
Logger . LogInformation ( "Successfully completed all database migrations." ) ;
Logger . LogInformation ( "You can safely end this process..." ) ;
}
private async Task MigrateDatabaseSchemaAsync ( Tenant tenant = null )
{
Logger . LogInformation (
$"Migrating schema for {(tenant == null ? " host " : tenant.Name + " tenant ")} database..." ) ;
foreach ( var migrator in _d bSchemaMigrators )
private async Task MigrateDatabaseSchemaAsync ( Tenant tenant = null )
{
await migrator . MigrateAsync ( ) ;
Logger . LogInformation (
$"Migrating schema for {(tenant == null ? " host " : tenant.Name + " tenant ")} database..." ) ;
foreach ( var migrator in _d bSchemaMigrators )
{
await migrator . MigrateAsync ( ) ;
}
}
}
private async Task SeedDataAsync ( Tenant tenant = null )
{
Logger . LogInformation ( $"Executing {(tenant == null ? " host " : tenant.Name + " tenant ")} database seed..." ) ;
private async Task SeedDataAsync ( Tenant tenant = null )
{
Logger . LogInformation ( $"Executing {(tenant == null ? " host " : tenant.Name + " tenant ")} database seed..." ) ;
await _d ataSeeder . SeedAsync ( new DataSeedContext ( tenant ? . Id )
. WithProperty ( IdentityDataSeedContributor . AdminEmailPropertyName , IdentityDataSeedContributor . AdminEmailDefaultValue )
. WithProperty ( IdentityDataSeedContributor . AdminPasswordPropertyName , IdentityDataSeedContributor . AdminPasswordDefaultValue )
) ;
}
await _d ataSeeder . SeedAsync ( new DataSeedContext ( tenant ? . Id )
. WithProperty ( IdentityDataSeedContributor . AdminEmailPropertyName , IdentityDataSeedContributor . AdminEmailDefaultValue )
. WithProperty ( IdentityDataSeedContributor . AdminPasswordPropertyName , IdentityDataSeedContributor . AdminPasswordDefaultValue )
) ;
}
private bool AddInitialMigrationIfNotExist ( )
{
try
private bool AddInitialMigrationIfNotExist ( )
{
if ( ! DbMigrationsProjectExists ( ) )
try
{
if ( ! DbMigrationsProjectExists ( ) )
{
return false ;
}
}
catch ( Exception )
{
return false ;
}
}
catch ( Exception )
{
return false ;
}
try
{
if ( ! MigrationsFolderExists ( ) )
try
{
AddInitialMigration ( ) ;
return true ;
if ( ! MigrationsFolderExists ( ) )
{
AddInitialMigration ( ) ;
return true ;
}
else
{
return false ;
}
}
else
catch ( Exc eption e )
{
Logger . LogWarning ( "Couldn't determinate if any migrations exist : " + e . Message ) ;
return false ;
}
}
catch ( Exception e )
{
Logger . LogWarning ( "Couldn't determinate if any migrations exist : " + e . Message ) ;
return false ;
}
}
private bool DbMigrationsProjectExists ( )
{
var dbMigrationsProjectFolder = GetEntityFrameworkCore ProjectFolderPath ( ) ;
private bool DbMigrationsProjectExists ( )
{
var dbMigrationsProjectFolder = GetDbMigrationsProjectFolderPath ( ) ;
return dbMigrationsProjectFolder ! = null ;
}
return dbMigrationsProjectFolder ! = null ;
}
private bool MigrationsFolderExists ( )
{
var dbMigrationsProjectFolder = GetEntityFrameworkCore ProjectFolderPath ( ) ;
private bool MigrationsFolderExists ( )
{
var dbMigrationsProjectFolder = GetDbMigrations ProjectFolderPath ( ) ;
return Directory . Exists ( Path . Combine ( dbMigrationsProjectFolder , "Migrations " ) ) ;
}
return Directory . Exists ( Path . Combine ( dbMigrationsProjectFolder , "EntityFrameworkCore " ) ) ;
}
private void AddInitialMigration ( )
{
Logger . LogInformation ( "Creating initial migration..." ) ;
private void AddInitialMigration ( )
{
Logger . LogInformation ( "Creating initial migration..." ) ;
string argumentPrefix ;
string fileName ;
string argumentPrefix ;
string fileName ;
if ( RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) | | RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
{
argumentPrefix = "-c" ;
fileName = "/bin/bash" ;
}
else
{
argumentPrefix = "/C" ;
fileName = "cmd.exe" ;
}
if ( RuntimeInformation . IsOSPlatform ( OSPlatform . OSX ) | | RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) )
{
argumentPrefix = "-c" ;
fileName = "/bin/bash" ;
}
else
{
argumentPrefix = "/C" ;
fileName = "cmd.exe" ;
}
var procStartInfo = new ProcessStartInfo ( fileName ,
$"{argumentPrefix} \" abp create - migration - and - run - migrator \ "{GetEntityFrameworkCore ProjectFolderPath()}\"\""
) ;
var procStartInfo = new ProcessStartInfo ( fileName ,
$"{argumentPrefix} \" abp create - migration - and - run - migrator \ "{GetDbMigrations ProjectFolderPath()}\"\""
) ;
try
{
Process . Start ( procStartInfo ) ;
}
catch ( Exception )
{
throw new Exception ( "Couldn't run ABP CLI..." ) ;
try
{
Process . Start ( procStartInfo ) ;
}
catch ( Exception )
{
throw new Exception ( "Couldn't run ABP CLI..." ) ;
}
}
}
private string GetEntityFrameworkCoreProjectFolderPath ( )
{
var slnDirectoryPath = GetSolutionDirectoryPath ( ) ;
if ( slnDirectoryPath = = null )
private string GetDbMigrationsProjectFolderPath ( )
{
throw new Exception ( "Solution folder not found!" ) ;
}
var slnDirectoryPath = GetSolutionDirectoryPath ( ) ;
var srcDirectoryPath = Path . Combine ( slnDirectoryPath , "src" ) ;
if ( slnDirectoryPath = = null )
{
throw new Exception ( "Solution folder not found!" ) ;
}
return Directory . GetDirectories ( srcDirectoryPath )
. FirstOrDefault ( d = > d . EndsWith ( ".EntityFrameworkCore" ) ) ;
}
var srcDirectoryPath = Path . Combine ( slnDirectoryPath , "src" ) ;
private string GetSolutionDirectoryPath ( )
{
var currentDirectory = new DirectoryInfo ( Directory . GetCurrentDirectory ( ) ) ;
return Directory . GetDirectories ( srcDirectoryPath )
. FirstOrDefault ( d = > d . EndsWith ( ".DbMigrations" ) ) ;
}
while ( Directory . GetParent ( currentDirectory . FullName ) ! = null )
private string GetSolutionDirectoryPath ( )
{
currentDirectory = Directory . GetParent ( currentDirectory . FullName ) ;
var currentDirectory = new DirectoryInfo ( Directory . GetCurrentDirectory ( ) ) ;
if ( Directory . GetFiles ( currentDirectory . FullName ) . FirstOrDefault ( f = > f . EndsWith ( ".sln" ) ) ! = null )
while ( Directory . GetParent ( currentDirectory . FullName ) ! = null )
{
return currentDirectory . FullName ;
currentDirectory = Directory . GetParent ( currentDirectory . FullName ) ;
if ( Directory . GetFiles ( currentDirectory . FullName ) . FirstOrDefault ( f = > f . EndsWith ( ".sln" ) ) ! = null )
{
return currentDirectory . FullName ;
}
}
}
return null ;
return null ;
}
}
}