Merge pull request 'v2 在初始化表结构之前和初始化种子数据之后的反射回调,通过系统版本比较,方便系统内部的表结构、种子数据的平滑升级。' (#309) from Junong/Admin.NET.Pro:v2 into v2
Reviewed-on: https://code.adminnet.top/Admin.NET/Admin.NET.Pro/pulls/309
This commit is contained in:
commit
db9276b1f5
@ -19,4 +19,52 @@ public class Startup : AppStartup
|
|||||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化与升级数据,在初始化表结构之前调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dbProvider"></param>
|
||||||
|
/// <param name="oldVerion">旧版本,0表示从来没有设置过,-1表示当前连接不是主数据库,从SysConfig表获取的</param>
|
||||||
|
/// <param name="currentVersion">当前版本,由ConfigConst.SysCurrentVersion转换的整数版本</param>
|
||||||
|
public void BeforeInitTable(SqlSugarScopeProvider dbProvider, long oldVerion, long currentVersion)
|
||||||
|
{
|
||||||
|
//比较版本号对数据库进行升级结构、种子数据等
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化与升级数据,在初始化种子数据之后调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dbProvider"></param>
|
||||||
|
/// <param name="oldVerion">旧版本,0表示从来没有设置过,-1表示当前连接不是主数据库,从SysConfig表获取的</param>
|
||||||
|
/// <param name="currentVersion">当前版本,由ConfigConst.SysCurrentVersion转换的整数版本</param>
|
||||||
|
public void AfterInitSeed(SqlSugarScopeProvider dbProvider, long oldVerion, long currentVersion)
|
||||||
|
{
|
||||||
|
//比较版本号对数据库进行升级结构、种子数据等
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 测试InitDatas,Order越大,InitDatas执行越靠前
|
||||||
|
/// </summary>
|
||||||
|
[AppStartup(1000)]
|
||||||
|
public class TestStartup : AppStartup
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化与升级数据,在初始化表结构之前调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dbProvider"></param>
|
||||||
|
/// <param name="oldVerion">旧版本,0表示从来没有设置过,-1表示当前连接不是主数据库,从SysConfig表获取的</param>
|
||||||
|
/// <param name="currentVersion">当前版本,由ConfigConst.SysCurrentVersion转换的整数版本</param>
|
||||||
|
public void BeforeInitTable(SqlSugarScopeProvider dbProvider, long oldVerion, long currentVersion)
|
||||||
|
{
|
||||||
|
//比较版本号对数据库进行升级结构、种子数据等
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化与升级数据,在初始化种子数据之后调用
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dbProvider"></param>
|
||||||
|
/// <param name="oldVerion">旧版本,0表示从来没有设置过,-1表示当前连接不是主数据库,从SysConfig表获取的</param>
|
||||||
|
/// <param name="currentVersion">当前版本,由ConfigConst.SysCurrentVersion转换的整数版本</param>
|
||||||
|
public void AfterInitSeed(SqlSugarScopeProvider dbProvider, long oldVerion, long currentVersion)
|
||||||
|
{
|
||||||
|
//比较版本号对数据库进行升级结构、种子数据等
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -11,6 +11,15 @@ namespace Admin.NET.Core;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ConfigConst
|
public class ConfigConst
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 系统版本code
|
||||||
|
/// </summary>
|
||||||
|
public const string SysVersion = "sys_version";
|
||||||
|
/// <summary>
|
||||||
|
/// 当前系统版本值,标准版本号为 x.xx.xxxxxx。比如 1.01.250409,也可以是变体,比如 1.2.5 v1.2.5
|
||||||
|
/// </summary>
|
||||||
|
public const string SysCurrentVersion = "1.01.000001";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 演示环境
|
/// 演示环境
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -39,6 +39,8 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
|
|||||||
new SysConfig{ Id=1300000000261, Name="密码历史记录验证", Code=ConfigConst.SysPasswordRecord, Value="False", SysFlag=YesNoEnum.Y, Remark="是否验证历史密码禁止再次使用", OrderNo=210, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2024-12-17 00:00:00") },
|
new SysConfig{ Id=1300000000261, Name="密码历史记录验证", Code=ConfigConst.SysPasswordRecord, Value="False", SysFlag=YesNoEnum.Y, Remark="是否验证历史密码禁止再次使用", OrderNo=210, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2024-12-17 00:00:00") },
|
||||||
new SysConfig{ Id=1300000000271, Name="显示系统更新日志", Code=ConfigConst.SysUpgrade, Value="True", SysFlag=YesNoEnum.Y, Remark="是否显示系统更新日志", OrderNo=220, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2024-12-20 00:00:00") },
|
new SysConfig{ Id=1300000000271, Name="显示系统更新日志", Code=ConfigConst.SysUpgrade, Value="True", SysFlag=YesNoEnum.Y, Remark="是否显示系统更新日志", OrderNo=220, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2024-12-20 00:00:00") },
|
||||||
new SysConfig{ Id=1300000000281, Name="开启多语言切换", Code=ConfigConst.SysI18NSwitch, Value="True", SysFlag=YesNoEnum.Y, Remark="是否显示多语言切换按钮", OrderNo=230, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2024-12-20 00:00:00") },
|
new SysConfig{ Id=1300000000281, Name="开启多语言切换", Code=ConfigConst.SysI18NSwitch, Value="True", SysFlag=YesNoEnum.Y, Remark="是否显示多语言切换按钮", OrderNo=230, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2024-12-20 00:00:00") },
|
||||||
|
|
||||||
|
new SysConfig{ Id=1300000000999, Name="系统版本", Code=ConfigConst.SysVersion, Value="0", SysFlag=YesNoEnum.Y, Remark= "系统版本,用于自动升级,请勿手动填写", OrderNo=1000, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -352,6 +352,11 @@ public static class SqlSugarSetup
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int GetStartupOrder(Type type)
|
||||||
|
{
|
||||||
|
return !type.IsDefined(typeof(AppStartupAttribute), true) ? 0 : type.GetCustomAttribute<AppStartupAttribute>(true).Order;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 初始化数据库
|
/// 初始化数据库
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -368,6 +373,46 @@ public static class SqlSugarSetup
|
|||||||
if (config.DbType != SqlSugar.DbType.Oracle) dbProvider.DbMaintenance.CreateDatabase();
|
if (config.DbType != SqlSugar.DbType.Oracle) dbProvider.DbMaintenance.CreateDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 扫描所有继承 AppStartup 的类
|
||||||
|
var startups = App.EffectiveTypes
|
||||||
|
.Where(u => typeof(AppStartup).IsAssignableFrom(u) && u.IsClass && !u.IsAbstract && !u.IsGenericType)
|
||||||
|
.OrderByDescending(u => GetStartupOrder(u));
|
||||||
|
//数据库前处理
|
||||||
|
long oldVerion = 0, currentVersion = 0;
|
||||||
|
SysConfig versionCfg = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//获取旧版本号
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (dbProvider.CurrentConnectionConfig.ConfigId.ToString() == SqlSugarConst.MainConfigId)
|
||||||
|
{
|
||||||
|
versionCfg = dbProvider.Queryable<SysConfig>().Where(n => n.Code == ConfigConst.SysVersion).First();
|
||||||
|
oldVerion = versionCfg != null ? CommonUtil.ConvertVersionToLong(versionCfg.Value) : 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oldVerion = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex) { }
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
currentVersion = CommonUtil.ConvertVersionToLong(ConfigConst.SysCurrentVersion);
|
||||||
|
}
|
||||||
|
//执行
|
||||||
|
foreach (var type in startups)
|
||||||
|
{
|
||||||
|
var startup = Activator.CreateInstance(type) as AppStartup;
|
||||||
|
var initDataMethod = type.GetMethod("BeforeInitTable");
|
||||||
|
initDataMethod?.Invoke(startup, new[] { (object)dbProvider, oldVerion, currentVersion });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log.Information($"数据库前处理有错 {config.DbType} - {config.ConfigId} : {ex.Message}");
|
||||||
|
}
|
||||||
|
|
||||||
// 初始化表结构
|
// 初始化表结构
|
||||||
if (config.TableSettings.EnableInitTable)
|
if (config.TableSettings.EnableInitTable)
|
||||||
{
|
{
|
||||||
@ -408,6 +453,41 @@ public static class SqlSugarSetup
|
|||||||
|
|
||||||
// 初始化种子数据
|
// 初始化种子数据
|
||||||
if (config.SeedSettings.EnableInitSeed) InitSeedData(db, config);
|
if (config.SeedSettings.EnableInitSeed) InitSeedData(db, config);
|
||||||
|
|
||||||
|
//数据后处理
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//执行后处理
|
||||||
|
foreach (var type in startups)
|
||||||
|
{
|
||||||
|
var startup = Activator.CreateInstance(type) as AppStartup;
|
||||||
|
if (startup == null) continue;
|
||||||
|
var initDataMethod = type.GetMethod("AfterInitSeed");
|
||||||
|
if (initDataMethod == null) continue;
|
||||||
|
initDataMethod?.Invoke(startup, new[] { (object)dbProvider, oldVerion, currentVersion });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
string errr = $"数据库后处理有错 {config.DbType} - {config.ConfigId} : {ex.Message}";
|
||||||
|
Log.Information(errr);
|
||||||
|
Console.WriteLine(errr);
|
||||||
|
Console.WriteLine(ex.StackTrace);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
//最后更新版本
|
||||||
|
if (dbProvider.CurrentConnectionConfig.ConfigId.ToString() == SqlSugarConst.MainConfigId)
|
||||||
|
{
|
||||||
|
IEnumerable<SysConfig> cfgs =
|
||||||
|
[
|
||||||
|
new SysConfig{ Id=1300000000999, Name="系统版本", Code=ConfigConst.SysVersion, Value=ConfigConst.SysCurrentVersion, SysFlag=YesNoEnum.Y, Remark= "系统版本,用于自动升级,请勿手动填写", OrderNo=1000, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") }
|
||||||
|
];
|
||||||
|
var storage = dbProvider.StorageableByObject(cfgs.ToList()).ToStorage();
|
||||||
|
storage.AsInsertable.ExecuteCommand();
|
||||||
|
storage.AsUpdateable.ExecuteCommand();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@ -39,7 +39,49 @@ public static class CommonUtil
|
|||||||
return Math.Abs(hash1 + (hash2 * 1566083941));
|
return Math.Abs(hash1 + (hash2 * 1566083941));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 将版本号转换为长整型,版本格式要求 x.xx.xxxxxx,比如 v1.2.5=>102000005 V3.10.42=>310000042
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="version">x.xx.xxxxxx</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ArgumentException"></exception>
|
||||||
|
public static long ConvertVersionToLong(string version)
|
||||||
|
{
|
||||||
|
// 1. 移除所有字母(不区分大小写)
|
||||||
|
string noLetters = Regex.Replace(version, "[a-zA-Z]", "");
|
||||||
|
|
||||||
|
// 2. 按 '.' 分割版本号
|
||||||
|
string[] parts = noLetters.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
// 3. 确保至少有3部分,不足则补 "0"
|
||||||
|
if (parts.Length < 3)
|
||||||
|
{
|
||||||
|
Array.Resize(ref parts, 3);
|
||||||
|
for (int i = 0; i < parts.Length; i++)
|
||||||
|
{
|
||||||
|
parts[i] = string.IsNullOrEmpty(parts[i]) ? "0" : parts[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 格式化各部分:
|
||||||
|
// - part1: 至少1位(直接取)
|
||||||
|
// - part2: 补齐到2位(如 "2" → "02")
|
||||||
|
// - part3: 补齐到6位(如 "5" → "000005")
|
||||||
|
string part1 = parts[0];
|
||||||
|
string part2 = parts[1].PadLeft(2, '0');
|
||||||
|
string part3 = parts[2].PadLeft(6, '0');
|
||||||
|
|
||||||
|
// 5. 拼接所有部分并转换为 long
|
||||||
|
string combined = $"{part1}{part2}{part3}";
|
||||||
|
if (long.TryParse(combined, out long result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ArgumentException("版本号转换失败,结果超出 long 范围。");
|
||||||
|
}
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 生成百分数
|
/// 生成百分数
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user