public static async Task Backup(ISettingsManager settingsManager, IDatabaseManager databaseManager, List <string> includes, List <string> excludes, int maxRows, TreeInfo treeInfo, string errorLogFilePath) { var allTableNames = await settingsManager.Database.GetTableNamesAsync(); var tableNames = new List <string>(); foreach (var tableName in allTableNames) { if (includes != null && !ListUtils.ContainsIgnoreCase(includes, tableName)) { continue; } if (ListUtils.ContainsIgnoreCase(excludes, tableName)) { continue; } if (ListUtils.ContainsIgnoreCase(tableNames, tableName)) { continue; } tableNames.Add(tableName); } await FileUtils.WriteTextAsync(treeInfo.TablesFilePath, TranslateUtils.JsonSerialize(tableNames)); await WriteUtils.PrintRowLineAsync(); await WriteUtils.PrintRowAsync("Backup table name", "Count"); await WriteUtils.PrintRowLineAsync(); foreach (var tableName in tableNames) { try { var columns = await settingsManager.Database.GetTableColumnsAsync(tableName); var repository = new Repository(settingsManager.Database, tableName, columns); var tableInfo = new TableInfo { Columns = repository.TableColumns, TotalCount = await repository.CountAsync(), RowFiles = new List <string>() }; if (maxRows > 0 && tableInfo.TotalCount > maxRows) { tableInfo.TotalCount = maxRows; } await WriteUtils.PrintRowAsync(tableName, tableInfo.TotalCount.ToString("#,0")); var identityColumnName = await settingsManager.Database.AddIdentityColumnIdIfNotExistsAsync(tableName, tableInfo.Columns); if (tableInfo.TotalCount > 0) { var current = 1; if (tableInfo.TotalCount > CliConstants.PageSize) { var pageCount = (int)Math.Ceiling((double)tableInfo.TotalCount / CliConstants.PageSize); using (var progress = new ProgressBar()) { for (; current <= pageCount; current++) { progress.Report((double)(current - 1) / pageCount); var fileName = $"{current}.json"; tableInfo.RowFiles.Add(fileName); var offset = (current - 1) * CliConstants.PageSize; var limit = tableInfo.TotalCount - offset < CliConstants.PageSize ? tableInfo.TotalCount - offset : CliConstants.PageSize; var rows = await databaseManager.GetPageObjectsAsync(tableName, identityColumnName, offset, limit); await FileUtils.WriteTextAsync( treeInfo.GetTableContentFilePath(tableName, fileName), TranslateUtils.JsonSerialize(rows)); } } } else { var fileName = $"{current}.json"; tableInfo.RowFiles.Add(fileName); var rows = await databaseManager.GetObjectsAsync(tableName); await FileUtils.WriteTextAsync(treeInfo.GetTableContentFilePath(tableName, fileName), TranslateUtils.JsonSerialize(rows)); } } await FileUtils.WriteTextAsync(treeInfo.GetTableMetadataFilePath(tableName), TranslateUtils.JsonSerialize(tableInfo)); } catch (Exception ex) { await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { Exception = ex, DateTime = DateTime.Now, Detail = tableName }); } } }
public static async Task Restore(List <string> includes, List <string> excludes, bool dataOnly, string tablesFilePath, TreeInfo treeInfo, string errorLogFilePath) { var tableNames = TranslateUtils.JsonDeserialize <List <string> >(await FileUtils.ReadTextAsync(tablesFilePath, Encoding.UTF8)); foreach (var tableName in tableNames) { try { if (includes != null) { if (!StringUtils.ContainsIgnoreCase(includes, tableName)) { continue; } } if (excludes != null) { if (StringUtils.ContainsIgnoreCase(excludes, tableName)) { continue; } } var metadataFilePath = treeInfo.GetTableMetadataFilePath(tableName); if (!FileUtils.IsFileExists(metadataFilePath)) { continue; } var tableInfo = TranslateUtils.JsonDeserialize <TableInfo>( await FileUtils.ReadTextAsync(metadataFilePath, Encoding.UTF8)); await CliUtils.PrintRowAsync(tableName, tableInfo.TotalCount.ToString("#,0")); if (DataProvider.DatabaseDao.IsTableExists(tableName)) { DataProvider.DatabaseDao.DropTable(tableName); } if (!DataProvider.DatabaseDao.CreateTable(tableName, tableInfo.Columns, out var ex, out var sqlString)) { await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"创建表 {tableName}: {sqlString}", Exception = ex }); continue; } if (tableInfo.RowFiles.Count > 0) { using (var progress = new ProgressBar()) { for (var i = 0; i < tableInfo.RowFiles.Count; i++) { progress.Report((double)i / tableInfo.RowFiles.Count); var fileName = tableInfo.RowFiles[i]; var objects = TranslateUtils.JsonDeserialize <List <JObject> >( await FileUtils.ReadTextAsync(treeInfo.GetTableContentFilePath(tableName, fileName), Encoding.UTF8)); try { DataProvider.DatabaseDao.InsertMultiple(tableName, objects, tableInfo.Columns); } catch (Exception exception) { await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"插入表 {tableName}, 文件名 {fileName}", Exception = exception }); } } } } } catch (Exception ex) { await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"插入表 {tableName}", Exception = ex }); } } await CliUtils.PrintRowLineAsync(); if (WebConfigUtils.DatabaseType == DatabaseType.Oracle) { var tableNameList = DataProvider.DatabaseDao.GetTableNameList(); foreach (var tableName in tableNameList) { DataProvider.DatabaseDao.AlterOracleAutoIncresementIdToMaxValue(tableName); } } if (!dataOnly) { // 恢复后同步表,确保内容辅助表字段与系统一致 SystemManager.SyncContentTables(); SystemManager.UpdateConfigVersion(); } }
public static async Task Execute(IJobContext context) { if (!CliUtils.ParseArgs(Options, context.Args)) { return; } if (_isHelp) { PrintUsage(); return; } if (string.IsNullOrEmpty(_directory)) { await CliUtils.PrintErrorAsync("需要指定恢复数据的文件夹名称:directory"); return; } var treeInfo = new TreeInfo(_directory); if (!DirectoryUtils.IsDirectoryExists(treeInfo.DirectoryPath)) { await CliUtils.PrintErrorAsync($"恢复数据的文件夹 {treeInfo.DirectoryPath} 不存在"); return; } var tablesFilePath = treeInfo.TablesFilePath; if (!FileUtils.IsFileExists(tablesFilePath)) { await CliUtils.PrintErrorAsync($"恢复文件 {treeInfo.TablesFilePath} 不存在"); return; } var webConfigPath = CliUtils.GetWebConfigPath(_configFile); if (!FileUtils.IsFileExists(webConfigPath)) { await CliUtils.PrintErrorAsync($"系统配置文件不存在:{webConfigPath}!"); return; } WebConfigUtils.Load(CliUtils.PhysicalApplicationPath, webConfigPath); if (string.IsNullOrEmpty(WebConfigUtils.ConnectionString)) { await CliUtils.PrintErrorAsync($"{webConfigPath} 中数据库连接字符串 connectionString 未设置"); return; } await Console.Out.WriteLineAsync($"数据库类型: {WebConfigUtils.DatabaseType.Value}"); await Console.Out.WriteLineAsync($"连接字符串: {WebConfigUtils.ConnectionString}"); await Console.Out.WriteLineAsync($"恢复文件夹: {treeInfo.DirectoryPath}"); if (!DataProvider.DatabaseDao.IsConnectionStringWork(WebConfigUtils.DatabaseType, WebConfigUtils.ConnectionString)) { await CliUtils.PrintErrorAsync($"系统无法连接到 {webConfigPath} 中设置的数据库"); return; } if (!_dataOnly) { if (SystemManager.IsInstalled) { await CliUtils.PrintErrorAsync("数据无法在已安装系统的数据库中恢复,命令执行失败"); return; } // 恢复前先创建表,确保系统在恢复的数据库中能够使用 SystemManager.CreateSiteServerTables(); } var tableNames = TranslateUtils.JsonDeserialize <List <string> >(await FileUtils.ReadTextAsync(tablesFilePath, Encoding.UTF8)); await CliUtils.PrintRowLineAsync(); await CliUtils.PrintRowAsync("恢复表名称", "总条数"); await CliUtils.PrintRowLineAsync(); var errorLogFilePath = CliUtils.CreateErrorLogFile(CommandName); foreach (var tableName in tableNames) { try { if (_includes != null) { if (!StringUtils.ContainsIgnoreCase(_includes, tableName)) { continue; } } if (_excludes != null) { if (StringUtils.ContainsIgnoreCase(_excludes, tableName)) { continue; } } var metadataFilePath = treeInfo.GetTableMetadataFilePath(tableName); if (!FileUtils.IsFileExists(metadataFilePath)) { continue; } var tableInfo = TranslateUtils.JsonDeserialize <TableInfo>(await FileUtils.ReadTextAsync(metadataFilePath, Encoding.UTF8)); await CliUtils.PrintRowAsync(tableName, tableInfo.TotalCount.ToString("#,0")); if (!DataProvider.DatabaseDao.IsTableExists(tableName)) { if (!DataProvider.DatabaseDao.CreateTable(tableName, tableInfo.Columns, out var ex, out var sqlString)) { await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"创建表 {tableName}: {sqlString}", Exception = ex }); continue; } } else { DataProvider.DatabaseDao.AlterSystemTable(tableName, tableInfo.Columns); } if (tableInfo.RowFiles.Count > 0) { using (var progress = new ProgressBar()) { for (var i = 0; i < tableInfo.RowFiles.Count; i++) { progress.Report((double)i / tableInfo.RowFiles.Count); var fileName = tableInfo.RowFiles[i]; var objects = TranslateUtils.JsonDeserialize <List <JObject> >( await FileUtils.ReadTextAsync(treeInfo.GetTableContentFilePath(tableName, fileName), Encoding.UTF8)); try { DataProvider.DatabaseDao.InsertMultiple(tableName, objects, tableInfo.Columns); } catch (Exception ex) { await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"插入表 {tableName}, 文件名 {fileName}", Exception = ex }); } } } } } catch (Exception ex) { await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"插入表 {tableName}", Exception = ex }); } } await CliUtils.PrintRowLineAsync(); if (WebConfigUtils.DatabaseType == DatabaseType.Oracle) { var tableNameList = DataProvider.DatabaseDao.GetTableNameList(); foreach (var tableName in tableNameList) { DataProvider.DatabaseDao.AlterOracleAutoIncresementIdToMaxValue(tableName); } } if (!_dataOnly) { // 恢复后同步表,确保内容辅助表字段与系统一致 SystemManager.SyncContentTables(); SystemManager.UpdateConfigVersion(); } await Console.Out.WriteLineAsync($"恭喜,成功从文件夹:{treeInfo.DirectoryPath} 恢复数据!"); }
private async Task RunAsync(IJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) { return; } if (_isHelp) { PrintUsage(); return; } if (string.IsNullOrEmpty(_directory)) { await CliUtils.PrintErrorAsync("需要指定恢复数据的文件夹名称:directory"); return; } var treeInfo = new TreeInfo(_settings.ContentRootPath, _directory); if (!Directory.Exists(treeInfo.DirectoryPath)) { await CliUtils.PrintErrorAsync($"恢复数据的文件夹 {treeInfo.DirectoryPath} 不存在"); return; } var tablesFilePath = treeInfo.TablesFilePath; if (!CliUtils.FileExists(tablesFilePath)) { await CliUtils.PrintErrorAsync($"恢复文件 {treeInfo.TablesFilePath} 不存在"); return; } var(isConnectionWorks, errorMessage) = await CliUtils.CheckSettingsAsync(_settings); if (!isConnectionWorks) { await CliUtils.PrintErrorAsync(errorMessage); return; } await Console.Out.WriteLineAsync($"数据库类型: {_settings.Database.DatabaseType.GetDisplayName()}"); await Console.Out.WriteLineAsync($"连接字符串: {_settings.Database.ConnectionString}"); await Console.Out.WriteLineAsync($"恢复文件夹: {treeInfo.DirectoryPath}"); var tableNames = Utilities.JsonDeserialize <List <string> >(await CliUtils.ReadAllTextAsync(tablesFilePath)); await CliUtils.PrintRowLineAsync(); await CliUtils.PrintRowAsync("恢复表名称", "总条数"); await CliUtils.PrintRowLineAsync(); var includes = new List <string>(_settings.Includes); var excludes = new List <string>(_settings.Excludes); var errorLogFilePath = CliUtils.CreateErrorLogFile(_settings.ContentRootPath, CommandName); foreach (var tableName in tableNames) { try { if (includes.Count > 0 && !Utilities.ContainsIgnoreCase(includes, tableName)) { continue; } if (excludes.Count > 0 && Utilities.ContainsIgnoreCase(excludes, tableName)) { continue; } var metadataFilePath = treeInfo.GetTableMetadataFilePath(tableName); if (!CliUtils.FileExists(metadataFilePath)) { continue; } var tableInfo = Utilities.JsonDeserialize <TableInfo>(await CliUtils.ReadAllTextAsync(metadataFilePath)); var repository = new Repository(_settings.Database, tableName, tableInfo.Columns); await CliUtils.PrintRowAsync(tableName, tableInfo.TotalCount.ToString("#,0")); if (!await _settings.Database.IsTableExistsAsync(tableName)) { try { await _settings.Database.CreateTableAsync(tableName, tableInfo.Columns); } catch (Exception ex) { await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"创建表 {tableName}", Exception = ex }); continue; } } else { await _settings.Database.AlterTableAsync(tableName, tableInfo.Columns); } if (tableInfo.RowFiles.Count > 0) { using (var progress = new ProgressBar()) { for (var i = 0; i < tableInfo.RowFiles.Count; i++) { progress.Report((double)i / tableInfo.RowFiles.Count); var fileName = tableInfo.RowFiles[i]; var objects = Utilities.JsonDeserialize <List <JObject> >( await CliUtils.ReadAllTextAsync(treeInfo.GetTableContentFilePath(tableName, fileName))); try { await repository.BulkInsertAsync(objects); } catch (Exception ex) { await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"插入表 {tableName}, 文件名 {fileName}", Exception = ex }); } } } } } catch (Exception ex) { await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"插入表 {tableName}", Exception = ex }); } } await CliUtils.PrintRowLineAsync(); await Console.Out.WriteLineAsync($"恭喜,成功从文件夹:{treeInfo.DirectoryPath} 恢复数据!"); }
public async Task <List <string> > RestoreAsync(List <string> includes, List <string> excludes, string tablesFilePath, TreeInfo treeInfo, string errorLogFilePath) { var tableNames = TranslateUtils.JsonDeserialize <List <string> >(await FileUtils.ReadTextAsync(tablesFilePath, Encoding.UTF8)); var errorTableNames = new List <string>(); foreach (var tableName in tableNames) { try { if (includes != null) { if (!ListUtils.ContainsIgnoreCase(includes, tableName)) { continue; } } if (excludes != null) { if (ListUtils.ContainsIgnoreCase(excludes, tableName)) { continue; } } var metadataFilePath = treeInfo.GetTableMetadataFilePath(tableName); if (!FileUtils.IsFileExists(metadataFilePath)) { continue; } var tableInfo = TranslateUtils.JsonDeserialize <TableInfo>( await FileUtils.ReadTextAsync(metadataFilePath, Encoding.UTF8)); await WriteUtils.PrintRowAsync(tableName, tableInfo.TotalCount.ToString("#,0")); if (await _settingsManager.Database.IsTableExistsAsync(tableName)) { await _settingsManager.Database.DropTableAsync(tableName); } await _settingsManager.Database.CreateTableAsync(tableName, tableInfo.Columns); if (tableInfo.RowFiles.Count > 0) { using var progress = new ProgressBar(); for (var i = 0; i < tableInfo.RowFiles.Count; i++) { progress.Report((double)i / tableInfo.RowFiles.Count); var fileName = tableInfo.RowFiles[i]; var objects = TranslateUtils.JsonDeserialize <List <JObject> >( await FileUtils.ReadTextAsync(treeInfo.GetTableContentFilePath(tableName, fileName), Encoding.UTF8)); try { var repository = new Repository(_settingsManager.Database, tableName, tableInfo.Columns); await repository.BulkInsertAsync(objects); } catch (Exception exception) { errorTableNames.Add(tableName); await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"插入表 {tableName}, 文件名 {fileName}", Exception = exception }); } } } } catch (Exception ex) { errorTableNames.Add(tableName); await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { DateTime = DateTime.Now, Detail = $"插入表 {tableName}", Exception = ex }); } } await WriteUtils.PrintRowLineAsync(); return(errorTableNames); //if (!dataOnly) //{ // // 恢复后同步表,确保内容辅助表字段与系统一致 // await _databaseManager.SyncDatabaseAsync(); // //await _databaseManager.SyncContentTablesAsync(); // await _configRepository.UpdateConfigVersionAsync(_settingsManager.Version); //} }
public async Task ExecuteAsync(IPluginJobContext context) { if (!CliUtils.ParseArgs(_options, context.Args)) { return; } if (_isHelp) { PrintUsage(); return; } if (string.IsNullOrEmpty(_directory)) { await WriteUtils.PrintErrorAsync("Backup folder name not specified: --directory"); return; } var oldTreeInfo = new TreeInfo(_settingsManager, _directory); var newTreeInfo = new TreeInfo(_settingsManager, Folder); if (!DirectoryUtils.IsDirectoryExists(oldTreeInfo.DirectoryPath)) { await WriteUtils.PrintErrorAsync($"The backup folder does not exist: {oldTreeInfo.DirectoryPath}"); return; } DirectoryUtils.CreateDirectoryIfNotExists(newTreeInfo.DirectoryPath); _updateService.Load(oldTreeInfo, newTreeInfo); await Console.Out.WriteLineAsync($"Backup folder: {oldTreeInfo.DirectoryPath}, Update folder: {newTreeInfo.DirectoryPath}, Update to SSCMS version: {_settingsManager.Version}"); var oldTableNames = TranslateUtils.JsonDeserialize <List <string> >(await FileUtils.ReadTextAsync(oldTreeInfo.TablesFilePath, Encoding.UTF8)); var newTableNames = new List <string>(); await WriteUtils.PrintRowLineAsync(); await WriteUtils.PrintRowAsync("Backup table name", "Update table Name", "Count"); await WriteUtils.PrintRowLineAsync(); var siteIdList = new List <int>(); var tableNames = new List <string>(); UpdateUtils.LoadSites(_settingsManager, oldTreeInfo, siteIdList, tableNames); var table = new TableContentConverter(_settingsManager); var splitSiteTableDict = new Dictionary <int, TableInfo>(); if (_splitContents) { var converter = table.GetSplitConverter(); foreach (var siteId in siteIdList) { splitSiteTableDict.Add(siteId, new TableInfo { Columns = converter.NewColumns, TotalCount = 0, RowFiles = new List <string>() }); } } var errorLogFilePath = CliUtils.DeleteErrorLogFileIfExists(_settingsManager); var errorTableNames = new List <string>(); foreach (var oldTableName in oldTableNames) { try { var oldMetadataFilePath = oldTreeInfo.GetTableMetadataFilePath(oldTableName); if (!FileUtils.IsFileExists(oldMetadataFilePath)) { continue; } var oldTableInfo = TranslateUtils.JsonDeserialize <TableInfo>(await FileUtils.ReadTextAsync(oldMetadataFilePath, Encoding.UTF8)); if (ListUtils.ContainsIgnoreCase(tableNames, oldTableName)) { if (_splitContents) { var converter = table.GetConverter(oldTableName, oldTableInfo.Columns); await _updateService.UpdateSplitContentsTableInfoAsync(splitSiteTableDict, siteIdList, oldTableName, oldTableInfo, converter); } else { var converter = table.GetConverter(oldTableName, oldTableInfo.Columns); var tuple = await _updateService.GetNewTableInfoAsync(oldTableName, oldTableInfo, converter); if (tuple != null) { newTableNames.Add(tuple.Item1); await FileUtils.WriteTextAsync(newTreeInfo.GetTableMetadataFilePath(tuple.Item1), TranslateUtils.JsonSerialize(tuple.Item2)); } } } else { var tuple = await _updateService.UpdateTableInfoAsync(oldTableName, oldTableInfo); if (tuple != null) { newTableNames.Add(tuple.Item1); await FileUtils.WriteTextAsync(newTreeInfo.GetTableMetadataFilePath(tuple.Item1), TranslateUtils.JsonSerialize(tuple.Item2)); } } } catch (Exception ex) { errorTableNames.Add(oldTableName); await CliUtils.AppendErrorLogAsync(errorLogFilePath, new TextLogInfo { Exception = ex, DateTime = DateTime.Now, Detail = oldTableName }); } } if (_splitContents) { foreach (var siteId in siteIdList) { var siteTableInfo = splitSiteTableDict[siteId]; var siteTableName = UpdateUtils.GetSplitContentTableName(siteId); newTableNames.Add(siteTableName); await FileUtils.WriteTextAsync(newTreeInfo.GetTableMetadataFilePath(siteTableName), TranslateUtils.JsonSerialize(siteTableInfo)); } await UpdateUtils.UpdateSitesSplitTableNameAsync(_databaseManager, newTreeInfo, splitSiteTableDict); } await FileUtils.WriteTextAsync(newTreeInfo.TablesFilePath, TranslateUtils.JsonSerialize(newTableNames)); await WriteUtils.PrintRowLineAsync(); if (errorTableNames.Count == 0) { await WriteUtils.PrintSuccessAsync("Update the backup data to the new version successfully!"); } else { await WriteUtils.PrintErrorAsync($"Database update failed and the following table was not successfully update: {ListUtils.ToString(errorTableNames)}"); } }