10 changed files with 55 additions and 409 deletions
@ -0,0 +1,14 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net10.0</TargetFramework> |
|||
<AssemblyName>Lion.AbpPro.Nacos</AssemblyName> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="nacos-sdk-csharp.AspNetCore" Version="1.3.10" /> |
|||
<PackageReference Include="nacos-sdk-csharp.Extensions.Configuration" Version="1.3.10" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,38 @@ |
|||
using Microsoft.Extensions.Configuration; |
|||
|
|||
namespace Microsoft.Extensions.Hosting; |
|||
|
|||
public static class HostBuilderExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// 添加Nacos配置支持
|
|||
/// </summary>
|
|||
/// <param name="hostBuilder">主机构建器</param>
|
|||
/// <returns>主机构建器</returns>
|
|||
public static IHostBuilder UseNacos(this IHostBuilder hostBuilder) |
|||
{ |
|||
return hostBuilder.ConfigureAppConfiguration((context, builder) => |
|||
{ |
|||
var configuration = builder.Build(); |
|||
// 从配置文件读取Nacos相关配置
|
|||
// 默认会使用JSON解析器来解析存在Nacos Server的配置
|
|||
builder.AddNacosV2Configuration(configuration.GetSection("NacosConfig")); |
|||
}); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// 添加Nacos配置支持
|
|||
/// </summary>
|
|||
/// <param name="hostBuilder">主机构建器</param>
|
|||
/// <param name="sectionName">Nacos配置节名称,默认为"NacosConfig"</param>
|
|||
/// <returns>主机构建器</returns>
|
|||
public static IHostBuilder UseNacos(this IHostBuilder hostBuilder, string sectionName = "NacosConfig") |
|||
{ |
|||
return hostBuilder.ConfigureAppConfiguration((context, builder) => |
|||
{ |
|||
var configuration = builder.Build(); |
|||
// 从配置文件读取Nacos相关配置
|
|||
builder.AddNacosV2Configuration(configuration.GetSection(sectionName)); |
|||
}); |
|||
} |
|||
} |
|||
@ -1,213 +0,0 @@ |
|||
using System.Diagnostics; |
|||
using System.Runtime.InteropServices; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Logging.Abstractions; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace Lion.AbpPro.BasicManagement.Data |
|||
{ |
|||
public class AbpProDbMigrationService : ITransientDependency |
|||
{ |
|||
private ILogger<AbpProDbMigrationService> Logger { get; set; } |
|||
|
|||
private readonly IDataSeeder _dataSeeder; |
|||
private readonly IEnumerable<IAbpProDbSchemaMigrator> _dbSchemaMigrators; |
|||
private readonly ITenantRepository _tenantRepository; |
|||
private readonly ICurrentTenant _currentTenant; |
|||
|
|||
public AbpProDbMigrationService( |
|||
IDataSeeder dataSeeder, |
|||
IEnumerable<IAbpProDbSchemaMigrator> dbSchemaMigrators, |
|||
ITenantRepository tenantRepository, |
|||
ICurrentTenant currentTenant) |
|||
{ |
|||
_dataSeeder = dataSeeder; |
|||
_dbSchemaMigrators = dbSchemaMigrators; |
|||
_tenantRepository = tenantRepository; |
|||
_currentTenant = currentTenant; |
|||
|
|||
Logger = NullLogger<AbpProDbMigrationService>.Instance; |
|||
} |
|||
|
|||
public async Task MigrateAsync() |
|||
{ |
|||
var initialMigrationAdded = AddInitialMigrationIfNotExist(); |
|||
|
|||
if (initialMigrationAdded) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
Logger.LogInformation("Started database migrations..."); |
|||
|
|||
await MigrateDatabaseSchemaAsync(); |
|||
await SeedDataAsync(); |
|||
|
|||
Logger.LogInformation($"Successfully completed host database migrations."); |
|||
|
|||
var tenants = await _tenantRepository.GetListAsync(includeDetails: true); |
|||
|
|||
var migratedDatabaseSchemas = new HashSet<string>(); |
|||
foreach (var tenant in tenants) |
|||
{ |
|||
using (_currentTenant.Change(tenant.Id)) |
|||
{ |
|||
if (tenant.ConnectionStrings.Any()) |
|||
{ |
|||
var tenantConnectionStrings = tenant.ConnectionStrings |
|||
.Select(x => x.Value) |
|||
.ToList(); |
|||
|
|||
if (!migratedDatabaseSchemas.IsSupersetOf(tenantConnectionStrings)) |
|||
{ |
|||
await MigrateDatabaseSchemaAsync(tenant); |
|||
|
|||
migratedDatabaseSchemas.AddIfNotContains(tenantConnectionStrings); |
|||
} |
|||
} |
|||
|
|||
await SeedDataAsync(tenant); |
|||
} |
|||
|
|||
Logger.LogInformation($"Successfully completed {tenant.Name} tenant database migrations."); |
|||
} |
|||
|
|||
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 _dbSchemaMigrators) |
|||
{ |
|||
await migrator.MigrateAsync(); |
|||
} |
|||
} |
|||
|
|||
private async Task SeedDataAsync(Tenant tenant = null) |
|||
{ |
|||
Logger.LogInformation($"Executing {(tenant == null ? "host" : tenant.Name + " tenant")} database seed..."); |
|||
|
|||
await _dataSeeder.SeedAsync(new DataSeedContext(tenant?.Id) |
|||
.WithProperty(IdentityDataSeedContributor.AdminEmailPropertyName, IdentityDataSeedContributor.AdminEmailDefaultValue) |
|||
.WithProperty(IdentityDataSeedContributor.AdminPasswordPropertyName, IdentityDataSeedContributor.AdminPasswordDefaultValue) |
|||
); |
|||
} |
|||
|
|||
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; |
|||
} |
|||
} |
|||
|
|||
private bool DbMigrationsProjectExists() |
|||
{ |
|||
var dbMigrationsProjectFolder = GetDbMigrationsProjectFolderPath(); |
|||
|
|||
return dbMigrationsProjectFolder != null; |
|||
} |
|||
|
|||
private bool MigrationsFolderExists() |
|||
{ |
|||
var dbMigrationsProjectFolder = GetDbMigrationsProjectFolderPath(); |
|||
|
|||
return Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "EntityFrameworkCore")); |
|||
} |
|||
|
|||
private void AddInitialMigration() |
|||
{ |
|||
Logger.LogInformation("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 \"{GetDbMigrationsProjectFolderPath()}\"\"" |
|||
); |
|||
|
|||
try |
|||
{ |
|||
Process.Start(procStartInfo); |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
throw new Exception("Couldn't run ABP CLI..."); |
|||
} |
|||
} |
|||
|
|||
private string GetDbMigrationsProjectFolderPath() |
|||
{ |
|||
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(".DbMigrations")); |
|||
} |
|||
|
|||
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; |
|||
} |
|||
} |
|||
} |
|||
@ -1,7 +0,0 @@ |
|||
namespace Lion.AbpPro.BasicManagement.Data |
|||
{ |
|||
public interface IAbpProDbSchemaMigrator |
|||
{ |
|||
Task MigrateAsync(); |
|||
} |
|||
} |
|||
@ -1,15 +0,0 @@ |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Lion.AbpPro.BasicManagement.Data |
|||
{ |
|||
/* This is used if database provider does't define |
|||
* IAbpProDbSchemaMigrator implementation. |
|||
*/ |
|||
public class NullAbpProDbSchemaMigrator : IAbpProDbSchemaMigrator, ITransientDependency |
|||
{ |
|||
public Task MigrateAsync() |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
} |
|||
@ -1,158 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Data; |
|||
|
|||
public class FileManagementDbMigrationService : ITransientDependency |
|||
{ |
|||
private readonly IDataSeeder _dataSeeder; |
|||
private readonly IEnumerable<IFileManagementDbSchemaMigrator> _dbSchemaMigrators; |
|||
|
|||
public FileManagementDbMigrationService( |
|||
IDataSeeder dataSeeder, |
|||
IEnumerable<IFileManagementDbSchemaMigrator> dbSchemaMigrators) |
|||
{ |
|||
_dataSeeder = dataSeeder; |
|||
_dbSchemaMigrators = dbSchemaMigrators; |
|||
Logger = NullLogger<FileManagementDbMigrationService>.Instance; |
|||
} |
|||
|
|||
public ILogger<FileManagementDbMigrationService> Logger { get; set; } |
|||
|
|||
public async Task MigrateAsync() |
|||
{ |
|||
var initialMigrationAdded = AddInitialMigrationIfNotExist(); |
|||
|
|||
if (initialMigrationAdded) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
Logger.LogInformation("Started database migrations..."); |
|||
await MigrateDatabaseSchemaAsync(); |
|||
await SeedDataAsync(); |
|||
Logger.LogInformation("Successfully completed host database migrations."); |
|||
Logger.LogInformation("You can safely end this process..."); |
|||
} |
|||
|
|||
private async Task MigrateDatabaseSchemaAsync() |
|||
{ |
|||
foreach (var migrator in _dbSchemaMigrators) |
|||
{ |
|||
await migrator.MigrateAsync(); |
|||
} |
|||
} |
|||
|
|||
private async Task SeedDataAsync() |
|||
{ |
|||
await _dataSeeder.SeedAsync(new DataSeedContext()); |
|||
} |
|||
|
|||
private bool AddInitialMigrationIfNotExist() |
|||
{ |
|||
try |
|||
{ |
|||
if (!DbMigrationsProjectExists()) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
try |
|||
{ |
|||
if (!MigrationsFolderExists()) |
|||
{ |
|||
AddInitialMigration(); |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
catch (Exception e) |
|||
{ |
|||
Logger.LogWarning("Couldn't determinate if any migrations exist : " + e.Message); |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
private bool DbMigrationsProjectExists() |
|||
{ |
|||
var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); |
|||
|
|||
return dbMigrationsProjectFolder != null; |
|||
} |
|||
|
|||
private bool MigrationsFolderExists() |
|||
{ |
|||
var dbMigrationsProjectFolder = GetEntityFrameworkCoreProjectFolderPath(); |
|||
|
|||
return Directory.Exists(Path.Combine(dbMigrationsProjectFolder, "Migrations")); |
|||
} |
|||
|
|||
private void AddInitialMigration() |
|||
{ |
|||
Logger.LogInformation("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..."); |
|||
} |
|||
} |
|||
|
|||
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")); |
|||
} |
|||
|
|||
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; |
|||
} |
|||
} |
|||
@ -1,6 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Data; |
|||
|
|||
public interface IFileManagementDbSchemaMigrator |
|||
{ |
|||
Task MigrateAsync(); |
|||
} |
|||
@ -1,9 +0,0 @@ |
|||
namespace Lion.AbpPro.FileManagement.Data; |
|||
|
|||
public class NullFileManagementDbSchemaMigrator : IFileManagementDbSchemaMigrator, ITransientDependency |
|||
{ |
|||
public Task MigrateAsync() |
|||
{ |
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
Loading…
Reference in new issue