abp
/Data
/
MyProjectNameDbMigrationService.cs
203 строки · 6.2 Кб
1using System.Diagnostics;2using System.Runtime.InteropServices;3using Microsoft.Extensions.Logging.Abstractions;4using Volo.Abp.Data;5using Volo.Abp.DependencyInjection;6using Volo.Abp.Identity;7using Volo.Abp.MultiTenancy;8using Volo.Abp.TenantManagement;9
10namespace MyCompanyName.MyProjectName.Data;11
12public class MyProjectNameDbMigrationService : ITransientDependency13{
14public ILogger<MyProjectNameDbMigrationService> Logger { get; set; }15
16private readonly IDataSeeder _dataSeeder;17private readonly MyProjectNameEFCoreDbSchemaMigrator _dbSchemaMigrator;18private readonly ITenantRepository _tenantRepository;19private readonly ICurrentTenant _currentTenant;20
21public MyProjectNameDbMigrationService(22IDataSeeder dataSeeder,23MyProjectNameEFCoreDbSchemaMigrator dbSchemaMigrator,24ITenantRepository tenantRepository,25ICurrentTenant currentTenant)26{27_dataSeeder = dataSeeder;28_dbSchemaMigrator = dbSchemaMigrator;29_tenantRepository = tenantRepository;30_currentTenant = currentTenant;31
32Logger = NullLogger<MyProjectNameDbMigrationService>.Instance;33}34
35public async Task MigrateAsync()36{37var initialMigrationAdded = AddInitialMigrationIfNotExist();38
39if (initialMigrationAdded)40{41return;42}43
44Logger.LogInformation("Started database migrations...");45
46await MigrateDatabaseSchemaAsync();47await SeedDataAsync();48
49Logger.LogInformation($"Successfully completed host database migrations.");50
51var tenants = await _tenantRepository.GetListAsync(includeDetails: true);52
53var migratedDatabaseSchemas = new HashSet<string>();54foreach (var tenant in tenants)55{56using (_currentTenant.Change(tenant.Id))57{58if (tenant.ConnectionStrings.Any())59{60var tenantConnectionStrings = tenant.ConnectionStrings61.Select(x => x.Value)62.ToList();63
64if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings))65{66await MigrateDatabaseSchemaAsync(tenant);67
68migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings);69}70}71
72await SeedDataAsync(tenant);73}74
75Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations.");76}77
78Logger.LogInformation("Successfully completed all database migrations.");79Logger.LogInformation("You can safely end this process...");80}81
82private async Task MigrateDatabaseSchemaAsync(Tenant? tenant = null)83{84Logger.LogInformation($"Migrating schema for {(tenant == null ? "host" : tenant.Name + " tenant")} database...");85await _dbSchemaMigrator.MigrateAsync();86}87
88private async Task SeedDataAsync(Tenant? tenant = null)89{90Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed...");91
92await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id)93.WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue)94.WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue)95);96}97
98private bool AddInitialMigrationIfNotExist()99{100try101{102if (!DbMigrationsProjectExists())103{104return false;105}106}107catch (Exception)108{109return false;110}111
112try113{114if (!MigrationsFolderExists())115{116AddInitialMigration();117return true;118}119else120{121return false;122}123}124catch (Exception e)125{126Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message);127return false;128}129}130
131private bool DbMigrationsProjectExists()132{133return Directory.Exists(GetEntityFrameworkCoreProjectFolderPath());134}135
136private bool MigrationsFolderExists()137{138var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath();139
140return Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations"));141}142
143private void AddInitialMigration()144{145Logger.LogInformation("Creating initial migration...");146
147string argumentPrefix;148string fileName;149
150if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux))151{152argumentPrefix = "-c";153fileName = "/bin/bash";154}155else156{157argumentPrefix = "/C";158fileName = "cmd.exe";159}160
161var procStartInfo = new ProcessStartInfo(fileName,162$"{argumentPrefix} \"abp create-migration-and-run-migrator \"{GetEntityFrameworkCoreProjectFolderPath()}\" --nolayers\""163);164
165try166{167Process.Start(procStartInfo);168}169catch (Exception)170{171throw new Exception("Couldn't run ABP CLI...");172}173}174
175private string GetEntityFrameworkCoreProjectFolderPath()176{177var slnDirectoryPath = GetSolutionDirectoryPath();178
179if (slnDirectoryPath == null)180{181throw new Exception("Solution folder not found!");182}183
184return Path.Combine(slnDirectoryPath, "MyCompanyName.MyProjectName.Mvc");185}186
187private string? GetSolutionDirectoryPath()188{189var currentDirectory = new DirectoryInfo(Directory.GetCurrentDirectory());190
191while (currentDirectory != null && Directory.GetParent(currentDirectory.FullName) != null)192{193currentDirectory = Directory.GetParent(currentDirectory.FullName);194
195if (currentDirectory != null && Directory.GetFiles(currentDirectory.FullName).FirstOrDefault(f => f.EndsWith(".sln")) != null)196{197return currentDirectory.FullName;198}199}200
201return null;202}203}
204