Files
zszq-trs/YLErpDAL/Modules/AppModule/UpgradModule/DbUpdateService.cs
T
2024-05-09 14:06:26 +08:00

305 lines
9.3 KiB
C#

using BaseOUDAL;
using YLErp.Commons;
namespace YLErp.Modules.AppModule.UpgradModule
{
/// <summary>
/// 数据库结构及数据升级服务
/// </summary>
public class DbUpdateService
{
const int UpState_Fail = -1;
const int UpState_Done = 1;
const int UpState_Pending = 0;
const string UpType_DbUpdate = "DbUpdate";
const string ResNameSpacePrefix = "YLErp.Resources.DbUpdate.Ver";
#region----获取资源文件列表----
/// <summary>
/// 获取资源文件列表
/// </summary>
public static List<DbUpdateDto> GetUpdateList()
{
var upList = new List<DbUpdateDto>();
var assembly = typeof(YLErp.Resources.PlaceHolder).Assembly;
foreach (var resName in assembly.GetManifestResourceNames())
{
//YLErp.Resources.DbUpdate.Ver_3._17.prod.sql
if (!resName.StartsWith(ResNameSpacePrefix))
{
continue;
}
var upkey = resName.Substring(ResNameSpacePrefix.Length, resName.Length - ResNameSpacePrefix.Length - 4);
var strArr = upkey.Split(new[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
var version = string.Join(".", strArr.Take(strArr.Length - 1).Select(n => n.Substring(1)).ToArray());
var dto = new DbUpdateDto
{
UpKey = upkey,
Version = version,
DbSchema = strArr[^1],
UpResult = "未执行"
};
upList.Add(dto);
}
var dic = GetLogs();
foreach (var dto in upList)
{
if (dic.TryGetValue(dto.UpKey, out var a))
{
dto.UpState = a.UpState;
dto.UpResult = a.UpResult;
}
}
return upList.OrderByDescending(x => x.Version + ".").ThenBy(n => n.DbSchema).ToList();
}
private static Dictionary<string, InnerDbLog> GetLogs()
{
InnerDbLog[] getLogs(DbSet<SysUpdateLog> dbset)
{
var startDate = DateTime.Today.AddMonths(-6);
var baseQry = from a in dbset
where a.CreateTime > startDate && a.UpType == UpType_DbUpdate
select a;
var groupQry = from a in baseQry
group a by a.UpKey into g
select new { id = g.Max(n => n.id) };
var listQry = from g in groupQry
join a in baseQry on g.id equals a.id
select new InnerDbLog
{
UpKey = a.UpKey,
UpResult = a.UpResult,
UpState = a.UpState
};
return listQry.ToArray();
}
var list = new List<InnerDbLog>(100);
using (var db = DbContextFactory.GetYLDbContext())
{
list.AddRange(getLogs(db.SysUpdateLogs));
}
using (var db = DbContextFactory.GetErpBaseContext())
{
list.AddRange(getLogs(db.SysUpdateLogs));
}
using (var db = DbContextFactory.GetClientDbContext(OptUserInfo.SystemUser))
{
list.AddRange(getLogs(db.SysUpdateLogs));
}
return CollectionHelper.ToDictionary2(list, n => n.UpKey, n => n, StringComparer.OrdinalIgnoreCase, useFirst: true);
}
#endregion
#region----执行数据库脚本升级----
/// <summary>
/// 执行数据库脚本升级
/// </summary>
public static List<DbUpdateResult> ExecuteUpdate(IEnumerable<string> upKeyList, bool onlyUpdateDone)
{
var resultList = new List<DbUpdateResult>();
var exelist = upKeyList.OrderBy(n => n.ToLowerInvariant()).ToArray();
foreach (var upkey in exelist)
{
var result = InnerExecuteUpdate(upkey, onlyUpdateDone);
resultList.Add(result);
}
return resultList;
}
/// <summary>
/// 执行单个更新
/// </summary>
private static DbUpdateResult InnerExecuteUpdate(string upkey, bool onlyUpdateDone)
{
var result = new DbUpdateResult { UpKey = upkey, UpState = UpState_Fail };
if (string.IsNullOrEmpty(upkey))
{
result.UpResult = "upkey是空值";
return result;
}
result.UpState = UpState_Pending;
var sqlText = string.Empty;
if (onlyUpdateDone)
{
result.UpState = UpState_Done;
result.UpResult = "手动更新为已执行";
}
else
{
sqlText = GetResourceContent(upkey);
if (sqlText == null)
{
result.UpState = UpState_Fail;
result.UpResult = "没有找到升级脚本";
}
else if (string.IsNullOrWhiteSpace(sqlText))
{
sqlText = string.Empty;
result.UpState = UpState_Done;
result.UpResult = "升级脚本为空";
}
}
using (var db = getDbContext(upkey))
{
if (db == null)
{
result.UpResult = "未从upkey中解析出正确的数据库";
return result;
}
if (result.UpState == UpState_Pending)
{
try
{
var changes = db.Database.ExecuteSqlRaw(sqlText);
result.UpState = UpState_Done;
result.UpResult = "执行成功,受影响的行数:" + changes;
}
catch (Exception ex)
{
result.UpState = UpState_Fail;
result.UpResult = ex.Messages();
}
}
var dblog = new SysUpdateLog()
{
UpKey = upkey,
UpType = UpType_DbUpdate,
UpState = result.UpState,
UpResult = result.UpResult,
CreateTime = DateTime.Now
};
db.SysUpdateLogs.Add(dblog);
db.SaveChanges();
}
return result;
DBContextBase getDbContext(string upkey)
{
var index = upkey.LastIndexOf('.');
var dbSchema = upkey.Substring(index + 1);
return (dbSchema?.ToLowerInvariant()) switch
{
"admin" => DbContextFactory.GetErpBaseContext(),
"client" => DbContextFactory.GetClientDbContext(OptUserInfo.SystemUser),
"prod" => DbContextFactory.GetYLDbContext(),
_ => null,
};
}
}
#endregion
/// <summary>
/// 查看数据库脚本升级内容
/// </summary>
public static string GetUpdateContent(IEnumerable<string> upKeyList)
{
if (upKeyList is null || !upKeyList.Any())
{
return string.Empty;
}
var sb = StringBuilderPool.Acquire();
var exelist = upKeyList.OrderBy(n =>
{
var index = n.LastIndexOf('.');
return n.Substring(0, index + 1);
}).ToArray();
foreach (var upkey in exelist)
{
var sqlText = GetResourceContent(upkey);
sb.AppendLine("-- -----------------------------------------------------------")
.Append("-- V").Append(upkey.Replace("_", "")).AppendLine()
.AppendLine("-- -----------------------------------------------------------");
if (sqlText == null)
{
sb.Append("-- !!!没有找到升级脚本:").Append(upkey).AppendLine();
}
else
{
sb.AppendLine(sqlText);
}
}
return sb.Release();
}
/// <summary>
/// 返回资源文件内容,如果是null表示资源不存在
/// </summary>
private static string GetResourceContent(string upkey)
{
var resName = string.Concat(ResNameSpacePrefix, upkey, ".sql");
var assembly = typeof(Resources.PlaceHolder).Assembly;
using var s = assembly.GetManifestResourceStream(resName);
if (s == null)
{
return null;
}
using var sr = new StreamReader(s);
return sr.ReadToEnd();
}
class InnerDbLog
{
public string UpKey { get; set; }
public string UpResult { get; set; }
public int UpState { get; set; }
}
}
}