using Microsoft.Extensions.Logging;
|
using System.Diagnostics;
|
using System.Runtime.InteropServices;
|
using Volo.Abp.Data;
|
using Volo.Abp.DependencyInjection;
|
|
namespace CMS.Plugin.WareCmsUtilityApi.Domain.Data;
|
|
/// <summary>
|
/// 数据库迁移服务
|
/// </summary>
|
public class CMSPluginDbMigrationService : ITransientDependency
|
{
|
private readonly IDataSeeder _dataSeeder;
|
private readonly IEnumerable<ICMSPluginDbSchemaMigrator> _dbSchemaMigrators;
|
private readonly ILogger<CMSPluginDbMigrationService> _logger;
|
|
/// <summary>
|
/// Initializes a new instance of the <see cref="CMSPluginDbMigrationService"/> class.
|
/// </summary>
|
/// <param name="dataSeeder">The data seeder.</param>
|
/// <param name="dbSchemaMigrators">The database schema migrators.</param>
|
/// <param name="logger">The logger.</param>
|
public CMSPluginDbMigrationService(IDataSeeder dataSeeder,
|
IEnumerable<ICMSPluginDbSchemaMigrator> dbSchemaMigrators, ILogger<CMSPluginDbMigrationService> logger)
|
{
|
_dataSeeder = dataSeeder;
|
_dbSchemaMigrators = dbSchemaMigrators;
|
_logger = logger;
|
}
|
|
/// <summary>
|
/// Migrates the asynchronous.
|
/// </summary>
|
public async Task MigrateAsync()
|
{
|
var initialMigrationAdded = AddInitialMigrationIfNotExist();
|
|
if (initialMigrationAdded)
|
{
|
return;
|
}
|
|
_logger.LogDebug("Started database migrations...");
|
|
await MigrateDatabaseSchemaAsync();
|
await SeedDataAsync();
|
|
_logger.LogDebug($"Successfully completed host database migrations.");
|
_logger.LogDebug("You can safely end this process...");
|
}
|
|
/// <summary>
|
/// Migrates the database schema asynchronous.
|
/// </summary>
|
private async Task MigrateDatabaseSchemaAsync()
|
{
|
_logger.LogDebug($"Migrating schema for database...");
|
|
foreach (var migrator in _dbSchemaMigrators)
|
{
|
await migrator.MigrateAsync();
|
}
|
}
|
|
/// <summary>
|
/// Seeds the data asynchronous.
|
/// </summary>
|
private async Task SeedDataAsync()
|
{
|
_logger.LogDebug($"Executing database seed...");
|
|
await _dataSeeder.SeedAsync(new DataSeedContext().WithProperty(CMSPluginDbProperties.ConnectionStringName, CMSPluginDbProperties.ConnectionStringName));
|
}
|
|
/// <summary>
|
/// Adds the initial migration if not exist.
|
/// </summary>
|
/// <returns></returns>
|
private bool AddInitialMigrationIfNotExist()
|
{
|
try
|
{
|
if (!DbMigrationsProjectExists())
|
{
|
return false;
|
}
|
}
|
catch (Exception)
|
{
|
return false;
|
}
|
|
try
|
{
|
if (!MigrationsFolderExists())
|
{
|
AddInitialMigration();
|
return true;
|
}
|
else
|
{
|
return false;
|
}
|
}
|
catch (Exception e)
|
{
|
_logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message);
|
return false;
|
}
|
}
|
|
/// <summary>
|
/// Databases the migrations project exists.
|
/// </summary>
|
/// <returns></returns>
|
private bool DbMigrationsProjectExists()
|
{
|
var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath();
|
|
return dbMigrationsProjectFolder != null;
|
}
|
|
/// <summary>
|
/// Migrationses the folder exists.
|
/// </summary>
|
/// <returns></returns>
|
private bool MigrationsFolderExists()
|
{
|
var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath();
|
|
return Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations"));
|
}
|
|
/// <summary>
|
/// Adds the initial migration.
|
/// </summary>
|
/// <exception cref="System.Exception">Couldn't run ABP CLI...</exception>
|
private void AddInitialMigration()
|
{
|
_logger.LogDebug("Creating initial migration...");
|
|
string argumentPrefix;
|
string fileName;
|
|
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 \"{GetEntityFrameworkCoreProjectFolderPath()}\"\""
|
);
|
|
try
|
{
|
Process.Start(procStartInfo);
|
}
|
catch (Exception)
|
{
|
throw new Exception("Couldn't run ABP CLI...");
|
}
|
}
|
|
/// <summary>
|
/// Gets the entity framework core project folder path.
|
/// </summary>
|
/// <returns></returns>
|
/// <exception cref="System.Exception">Solution folder not found!</exception>
|
private string GetEntityFrameworkCoreProjectFolderPath()
|
{
|
var slnDirectoryPath = GetSolutionDirectoryPath();
|
|
if (slnDirectoryPath == null)
|
{
|
throw new Exception("Solution folder not found!");
|
}
|
|
var srcDirectoryPath = Path.Combine(slnDirectoryPath, "src");
|
|
return Directory.GetDirectories(srcDirectoryPath)
|
.FirstOrDefault(d => d.EndsWith(".EntityFrameworkCore"));
|
}
|
|
/// <summary>
|
/// Gets the solution directory path.
|
/// </summary>
|
/// <returns></returns>
|
private string GetSolutionDirectoryPath()
|
{
|
var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());
|
|
while (Directory.GetParent(currentDirectory.FullName) != null)
|
{
|
currentDirectory = Directory.GetParent(currentDirectory.FullName);
|
|
if (Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null)
|
{
|
return currentDirectory.FullName;
|
}
|
}
|
|
return null;
|
}
|
}
|