305 lines
9.3 KiB
C#
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; }
|
|
}
|
|
}
|
|
}
|