| using Microsoft.Extensions.Logging; | 
| using System.Diagnostics; | 
| using System.Runtime.InteropServices; | 
| using Volo.Abp.Data; | 
| using Volo.Abp.DependencyInjection; | 
|   | 
| namespace CMS.Plugin.HIAWms.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; | 
|     } | 
| } |