using JNPF.Common.Core.Manager; using JNPF.Common.Enums; using JNPF.DatabaseAccessor; using JNPF.DependencyInjection; using JNPF.DynamicApiController; using JNPF.FriendlyException; using JNPF.Systems.Entitys.Dto.Database; using JNPF.Systems.Entitys.Dto.DataSync; using JNPF.Systems.Entitys.Dto.System.DataSync; using JNPF.Systems.Entitys.System; using JNPF.Systems.Interfaces.System; using Mapster; using Microsoft.AspNetCore.Mvc; using SqlSugar; namespace JNPF.Systems; /// /// 数据同步 /// 版 本:V3.2 /// 版 权:拓通智联科技有限公司(http://www.tuotong-tech.com) /// 日 期:2021-06-01. /// [ApiDescriptionSettings(Tag = "System", Name = "DataSync", Order = 209)] [Route("api/system/[controller]")] public class DataSyncService : IDynamicApiController, ITransient { /// /// 数据连接服务. /// private readonly IDbLinkService _dbLinkService; /// /// 服务基础仓储. /// public readonly ISqlSugarRepository _repository; /// /// 数据库管理. /// private readonly IDataBaseManager _dataBaseManager; /// /// 用户管理. /// private readonly IUserManager _userManager; /// /// 初始化一个类型的新实例. /// public DataSyncService( ISqlSugarRepository repository, IDataBaseManager dataBaseManager, IDbLinkService dbLinkService, IUserManager userManager) { _repository = repository; _dataBaseManager = dataBaseManager; _dbLinkService = dbLinkService; _userManager = userManager; } /// /// 同步判断. /// /// 请求参数. /// [HttpPost("")] public async Task Estimate([FromBody] DbSyncActionsExecuteInput input) { var linkFrom = await _dbLinkService.GetInfo(input.dbConnectionFrom); var linkTo = await _dbLinkService.GetInfo(input.dbConnectionTo) ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName); if (!IsNullDataByTable(linkFrom, input.dbTable)) { // 初始表有数据 return 1; } else if (!_dataBaseManager.IsAnyTable(linkTo, input.dbTable)) { // 目的表不存在 return 2; } else if (IsNullDataByTable(linkTo, input.dbTable)) { // 目的表有数据 return 3; } else { return 0; } } /// /// 执行同步. /// /// 请求参数. /// [HttpPost("Actions/Execute")] [UnitOfWork] public async Task Execute([FromBody] DbSyncActionsExecuteInput input) { var linkFrom = await _dbLinkService.GetInfo(input.dbConnectionFrom); var linkTo = await _dbLinkService.GetInfo(input.dbConnectionTo) ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName); if (linkFrom.DbType == linkTo.DbType) { input.convertRuleMap = null; } _dataBaseManager.SyncTable(linkFrom, linkTo, input.dbTable, input.type, input.convertRuleMap); if (!await ImportTableData(linkFrom, linkTo, input.dbTable)) throw Oops.Oh(ErrorCode.COM1006); } /// /// 执行同步批量. /// /// 请求参数. /// [HttpPost("Actions/batchExecute")] [UnitOfWork] public async Task batchExecute([FromBody] DbSyncActionsExecuteInput input) { var linkFrom = await _dbLinkService.GetInfo(input.dbConnectionFrom); var linkTo = await _dbLinkService.GetInfo(input.dbConnectionTo) ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName); if (linkFrom.DbType == linkTo.DbType) { input.convertRuleMap = null; } if (input.dbTableList.Any()) { foreach (var item in input.dbTableList) { _dataBaseManager.SyncTable(linkFrom, linkTo, item, input.type, input.convertRuleMap); if (!await ImportTableData(linkFrom, linkTo, item)) throw Oops.Oh(ErrorCode.COM1006); } } } /// /// 同步判断. /// /// 请求参数. /// [HttpPost("Actions/checkDbLink")] public async Task checkDbLink([FromBody] DbSyncActionsExecuteInput input) { var linkFrom = await _dbLinkService.GetInfo(input.dbConnectionFrom) ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName); var linkTo = await _dbLinkService.GetInfo(input.dbConnectionTo) ?? _dataBaseManager.GetTenantDbLink(_userManager.TenantId, _userManager.TenantDbName); var output = new DbSyncOutput(); output.checkDbFlag = _dataBaseManager.IsConnection(linkFrom) && _dataBaseManager.IsConnection(linkTo); var tables = _dataBaseManager.GetDBTableList(linkFrom); //tables = tables.Where((x, i) => tables.FindIndex(z => z.Name == x.Name) == i).ToList(); output.tableList = tables.Adapt>().OrderBy(x => x.table).ToList(); //foreach (var item in output.tableList) //{ // try // { // item.sum = _repository.AsSugarClient().Queryable().AS(item.table).Count(); // } // catch (Exception ex) // { // item.sum = 0; // } //} output.convertRuleMap = GetFieldType(linkFrom.DbType, linkTo.DbType); return output; } #region PrivateMethod /// /// 判断表中是否有数据. /// /// /// /// private bool IsNullDataByTable(DbLinkEntity entity, string table) { var data = _dataBaseManager.GetData(entity, table); if (data.Rows.Count > 0) return true; return false; } /// /// 批量写入. /// /// 数据库连接 From. /// 数据库连接To. /// private async Task ImportTableData(DbLinkEntity linkFrom, DbLinkEntity linkTo, string table) { try { // 取同步数据 var syncData = _dataBaseManager.GetData(linkFrom, table); // 插入同步数据 return await _dataBaseManager.SyncData(linkTo, syncData, table); } catch (Exception ex) { return false; } } /// /// 获取数据库类型. /// /// /// /// private Dictionary> GetFieldType(string dbTypeForm, string dbTypeTo) { var fieldTypeList = new Dictionary>(); switch (dbTypeForm.ToLower()) { case "sqlserver": fieldTypeList.Add("nvarchar", GetDataTypeList(0, dbTypeTo)); fieldTypeList.Add("int", GetDataTypeList(1, dbTypeTo)); fieldTypeList.Add("datetime", GetDataTypeList(2, dbTypeTo)); fieldTypeList.Add("decimal", GetDataTypeList(3, dbTypeTo)); fieldTypeList.Add("bigint", GetDataTypeList(4, dbTypeTo)); fieldTypeList.Add("nvarchar(max)", GetDataTypeList(5, dbTypeTo)); break; case "mysql": fieldTypeList.Add("varchar", GetDataTypeList(0, dbTypeTo)); fieldTypeList.Add("int", GetDataTypeList(1, dbTypeTo)); fieldTypeList.Add("datetime", GetDataTypeList(2, dbTypeTo)); fieldTypeList.Add("decimal", GetDataTypeList(3, dbTypeTo)); fieldTypeList.Add("bigint", GetDataTypeList(4, dbTypeTo)); fieldTypeList.Add("longtext", GetDataTypeList(5, dbTypeTo)); break; case "oracle": fieldTypeList.Add("varchar2", GetDataTypeList(0, dbTypeTo)); fieldTypeList.Add("number", GetDataTypeList(1, dbTypeTo)); fieldTypeList.Add("date", GetDataTypeList(2, dbTypeTo)); fieldTypeList.Add("number", GetDataTypeList(3, dbTypeTo)); fieldTypeList.Add("number", GetDataTypeList(4, dbTypeTo)); fieldTypeList.Add("clob", GetDataTypeList(5, dbTypeTo)); break; case "dm": fieldTypeList.Add("varchar", GetDataTypeList(0, dbTypeTo)); fieldTypeList.Add("int", GetDataTypeList(1, dbTypeTo)); fieldTypeList.Add("datetime", GetDataTypeList(2, dbTypeTo)); fieldTypeList.Add("decimal", GetDataTypeList(3, dbTypeTo)); fieldTypeList.Add("bigint", GetDataTypeList(4, dbTypeTo)); fieldTypeList.Add("text", GetDataTypeList(5, dbTypeTo)); break; case "postgresql": fieldTypeList.Add("nvarchar", GetDataTypeList(0, dbTypeTo)); fieldTypeList.Add("int4", GetDataTypeList(1, dbTypeTo)); fieldTypeList.Add("timestamp", GetDataTypeList(2, dbTypeTo)); fieldTypeList.Add("numeric", GetDataTypeList(3, dbTypeTo)); fieldTypeList.Add("int8", GetDataTypeList(4, dbTypeTo)); fieldTypeList.Add("text", GetDataTypeList(5, dbTypeTo)); break; case "kingbasees": fieldTypeList.Add("nvarchar", GetDataTypeList(0, dbTypeTo)); fieldTypeList.Add("integer", GetDataTypeList(1, dbTypeTo)); fieldTypeList.Add("date", GetDataTypeList(2, dbTypeTo)); fieldTypeList.Add("numeric", GetDataTypeList(3, dbTypeTo)); fieldTypeList.Add("bigint", GetDataTypeList(4, dbTypeTo)); fieldTypeList.Add("text", GetDataTypeList(5, dbTypeTo)); break; } return fieldTypeList; } private List GetDataTypeList(int type, string dbType) { var list = new List(); switch (dbType.ToLower()) { case "sqlserver": switch (type) { case 0: list.Add("nvarchar"); break; case 1: list.Add("int"); break; case 2: list.Add("datetime"); break; case 3: list.Add("decimal"); break; case 4: list.Add("bigint"); break; case 5: list.Add("nvarchar(max)"); break; } break; case "mysql": switch (type) { case 0: list.Add("varchar"); break; case 1: list.Add("int"); break; case 2: list.Add("datetime"); break; case 3: list.Add("decimal"); break; case 4: list.Add("bigint"); break; case 5: list.Add("longtext"); break; } break; case "oracle": switch (type) { case 0: list.Add("varchar2"); break; case 1: list.Add("number"); break; case 2: list.Add("date"); break; case 3: list.Add("number"); break; case 4: list.Add("number"); break; case 5: list.Add("clob"); break; } break; case "dm": switch (type) { case 0: list.Add("varchar"); break; case 1: list.Add("int"); break; case 2: list.Add("datetime"); break; case 3: list.Add("decimal"); break; case 4: list.Add("bigint"); break; case 5: list.Add("text"); break; } break; case "postgresql": switch (type) { case 0: list.Add("nvarchar"); break; case 1: list.Add("int4"); break; case 2: list.Add("timestamp"); break; case 3: list.Add("numeric"); break; case 4: list.Add("int8"); break; case 5: list.Add("text"); break; } break; case "kingbasees": switch (type) { case 0: list.Add("nvarchar"); break; case 1: list.Add("integer"); break; case 2: list.Add("date"); break; case 3: list.Add("numeric"); break; case 4: list.Add("bigint"); break; case 5: list.Add("text"); break; } break; } return list; } #endregion }