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
}