diff --git a/system/Tnb.Systems/System/DbLinkService.cs b/system/Tnb.Systems/System/DbLinkService.cs index 3ead4d4b..2ac46374 100644 --- a/system/Tnb.Systems/System/DbLinkService.cs +++ b/system/Tnb.Systems/System/DbLinkService.cs @@ -13,6 +13,7 @@ using JNPF.Systems.Entitys.System; using JNPF.Systems.Interfaces.System; using Mapster; using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Caching.Memory; using SqlSugar; namespace JNPF.Systems; @@ -27,293 +28,303 @@ namespace JNPF.Systems; [Route("api/system/[controller]")] public class DbLinkService : IDbLinkService, IDynamicApiController, ITransient { - /// - /// 服务基础仓储. - /// - private readonly ISqlSugarRepository _repository; + /// + /// 服务基础仓储. + /// + private readonly ISqlSugarRepository _repository; - /// - /// 数据字典服务. - /// - private readonly IDictionaryDataService _dictionaryDataService; + /// + /// 数据字典服务. + /// + private readonly IDictionaryDataService _dictionaryDataService; - /// - /// 数据库管理. - /// - private readonly IDataBaseManager _dataBaseManager; + /// + /// 数据库管理. + /// + private readonly IDataBaseManager _dataBaseManager; - /// - /// 初始化一个类型的新实例. - /// - public DbLinkService( - ISqlSugarRepository repository, - IDictionaryDataService dictionaryDataService, - IDataBaseManager dataBaseManager) + private readonly IMemoryCache _memCache; + + /// + /// 初始化一个类型的新实例. + /// + public DbLinkService( + ISqlSugarRepository repository, + IDictionaryDataService dictionaryDataService, + IDataBaseManager dataBaseManager, + IMemoryCache memCache) + { + _repository = repository; + _dictionaryDataService = dictionaryDataService; + _dataBaseManager = dataBaseManager; + _memCache = memCache; + } + + #region GET + + /// + /// 列表. + /// + /// + [HttpGet("")] + public async Task GetList([FromQuery] DbLinkListInput input) + { + var list = await _repository.AsSugarClient().Queryable( + (a, b, c) => new JoinQueryInfos(JoinType.Left, a.CreatorUserId == b.Id, JoinType.Left, a.LastModifyUserId == c.Id)) + .Where((a, b, c) => a.DeleteMark == null) + .WhereIF(input.dbType.IsNotEmptyOrNull(), (a, b, c) => a.DbType == input.dbType) + .WhereIF(input.keyword.IsNotEmptyOrNull(), (a, b, c) => a.FullName.Contains(input.keyword)) + .Select((a, b, c) => new DbLinkListOutput() + { + id = a.Id, + creatorTime = a.CreatorTime, + creatorUser = SqlFunc.MergeString(b.RealName, "/", b.Account), + dbType = a.DbType, + enabledMark = a.EnabledMark, + fullName = a.FullName, + host = a.Host, + lastModifyTime = a.LastModifyTime, + lastModifyUser = SqlFunc.MergeString(c.RealName, "/", c.Account), + port = a.Port.ToString(), + sortCode = a.SortCode + }).Distinct().MergeTable().OrderBy((a) => a.sortCode).OrderBy((a) => a.creatorTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); + return PageResult.SqlSugarPageResult(list); + } + + /// + /// 下拉框列表. + /// + /// + [HttpGet("Selector")] + public async Task GetSelector([FromQuery] string type) + { + var data = (await GetList()).Adapt>(); + + // 数据库分类 + var dbTypeList = (await _dictionaryDataService.GetList("dbType")).FindAll(x => x.EnabledMark == 1); + var output = new List(); + if (type.IsNullOrEmpty()) { - _repository = repository; - _dictionaryDataService = dictionaryDataService; - _dataBaseManager = dataBaseManager; + output.Add(new DbLinkSelectorOutput() + { + id = "-2", + parentId = "0", + fullName = "", + num = data.FindAll(x => x.parentId == null).Count + }); + var defaultDBType = App.GetConfig("ConnectionStrings", true).DBType; + if (defaultDBType.Equals("Kdbndp")) + { + defaultDBType = "KingbaseES"; + } + if (defaultDBType.Equals("Dm")) + { + defaultDBType = "DM8"; + } + output.Add(new DbLinkSelectorOutput() + { + id = "0", + parentId = "-2", + fullName = "默认数据库", + dbType = defaultDBType, + num = 1 + }); } - #region GET - - /// - /// 列表. - /// - /// - [HttpGet("")] - public async Task GetList([FromQuery] DbLinkListInput input) + output.Add(new DbLinkSelectorOutput() { - var list = await _repository.AsSugarClient().Queryable( - (a, b, c) => new JoinQueryInfos(JoinType.Left, a.CreatorUserId == b.Id, JoinType.Left, a.LastModifyUserId == c.Id)) - .Where((a, b, c) => a.DeleteMark == null) - .WhereIF(input.dbType.IsNotEmptyOrNull(), (a, b, c) => a.DbType == input.dbType) - .WhereIF(input.keyword.IsNotEmptyOrNull(), (a, b, c) => a.FullName.Contains(input.keyword)) - .Select((a, b, c) => new DbLinkListOutput() - { - id = a.Id, - creatorTime = a.CreatorTime, - creatorUser = SqlFunc.MergeString(b.RealName, "/", b.Account), - dbType = a.DbType, - enabledMark = a.EnabledMark, - fullName = a.FullName, - host = a.Host, - lastModifyTime = a.LastModifyTime, - lastModifyUser = SqlFunc.MergeString(c.RealName, "/", c.Account), - port = a.Port.ToString(), - sortCode = a.SortCode - }).Distinct().MergeTable().OrderBy((a) => a.sortCode).OrderBy((a) => a.creatorTime, OrderByType.Desc).ToPagedListAsync(input.currentPage, input.pageSize); - return PageResult.SqlSugarPageResult(list); - } + id = "-1", + parentId = "0", + fullName = "未分类", + num = data.FindAll(x => x.parentId == null).Count + }); - /// - /// 下拉框列表. - /// - /// - [HttpGet("Selector")] - public async Task GetSelector([FromQuery] string type) + foreach (var item in dbTypeList) { - var data = (await GetList()).Adapt>(); - - // 数据库分类 - var dbTypeList = (await _dictionaryDataService.GetList("dbType")).FindAll(x => x.EnabledMark == 1); - var output = new List(); - if (type.IsNullOrEmpty()) - { - output.Add(new DbLinkSelectorOutput() - { - id = "-2", - parentId = "0", - fullName = "", - num = data.FindAll(x => x.parentId == null).Count - }); - var defaultDBType = App.GetConfig("ConnectionStrings", true).DBType; - if (defaultDBType.Equals("Kdbndp")) - { - defaultDBType = "KingbaseES"; - } - if (defaultDBType.Equals("Dm")) - { - defaultDBType = "DM8"; - } - output.Add(new DbLinkSelectorOutput() - { - id = "0", - parentId = "-2", - fullName = "默认数据库", - dbType = defaultDBType, - num = 1 - }); - } - + var index = data.FindAll(x => x.dbType.Equals(item.EnCode)).Count; + if (index > 0) + { output.Add(new DbLinkSelectorOutput() { - id = "-1", - parentId = "0", - fullName = "未分类", - num = data.FindAll(x => x.parentId == null).Count + id = item.Id, + fullName = item.FullName }); + } + } - foreach (var item in dbTypeList) - { - var index = data.FindAll(x => x.dbType.Equals(item.EnCode)).Count; - if (index > 0) + return new { list = output.Union(data).ToList().ToTree() }; + } + + /// + /// 信息. + /// + /// 主键值. + /// + [HttpGet("{id}")] + public async Task GetInfo_Api(string id) + { + var data = await GetInfo(id); + var oracleParam = data.OracleParam?.ToObject(); + var output = data.Adapt(); + if (oracleParam.IsNotEmptyOrNull() && oracleParam.oracleExtend) + { + output.oracleService = oracleParam.oracleService; + output.oracleExtend = oracleParam.oracleExtend; + output.oracleLinkType = oracleParam.oracleLinkType; + output.oracleRole = oracleParam.oracleRole; + } + + return output; + } + #endregion + + #region POST + + /// + /// 删除. + /// + /// 主键值. + /// + [HttpDelete("{id}")] + public async Task Delete(string id) + { + var entity = await GetInfo(id); + _ = entity ?? throw Oops.Oh(ErrorCode.COM1005); + var isOk = await _repository.AsUpdateable(entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync(); + if (!isOk) + throw Oops.Oh(ErrorCode.COM1002); + } + + /// + /// 创建. + /// + /// 实体对象. + /// + [HttpPost("")] + public async Task Create_Api([FromBody] DbLinkCrInput input) + { + if (await _repository.IsAnyAsync(x => x.FullName == input.fullName && x.DeleteMark == null)) + throw Oops.Oh(ErrorCode.COM1004); + var entity = input.Adapt(); + if (input.oracleExtend) + { + entity.OracleParam = new OracleParamModel() + { + oracleExtend = input.oracleExtend, + oracleRole = input.oracleRole, + oracleLinkType = input.oracleLinkType, + oracleService = input.oracleService + }.ToJsonString(); + } + + var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); + if (isOk < 1) + throw Oops.Oh(ErrorCode.COM1000); + } + + /// + /// 编辑. + /// + /// 主键值. + /// 实体对象. + /// + [HttpPut("{id}")] + public async Task Update_Api(string id, [FromBody] DbLinkUpInput input) + { + if (await _repository.IsAnyAsync(x => x.Id != id && x.FullName == input.fullName && x.DeleteMark == null)) + throw Oops.Oh(ErrorCode.COM1004); + var entity = input.Adapt(); + if (input.oracleExtend) + { + entity.OracleParam = new OracleParamModel() + { + oracleExtend = input.oracleExtend, + oracleRole = input.oracleRole, + oracleLinkType = input.oracleLinkType, + oracleService = input.oracleService + }.ToJsonString(); + } + + var isOk = await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync(); + if (!isOk) + throw Oops.Oh(ErrorCode.COM1001); + } + + /// + /// 测试连接. + /// + /// 实体对象. + [HttpPost("Actions/Test")] + public void TestDbConnection([FromBody] DbLinkActionsTestInput input) + { + var entity = input.Adapt(); + entity.Id = input.id.Equals("0") ? SnowflakeIdHelper.NextId() : input.id; + if (input.oracleExtend) + { + entity.OracleParam = new OracleParamModel() + { + oracleExtend = input.oracleExtend, + oracleRole = input.oracleRole, + oracleLinkType = input.oracleLinkType, + oracleService = input.oracleService + }.ToJsonString(); + } + + if (!_dataBaseManager.IsConnection(entity)) + throw Oops.Oh(ErrorCode.D1507); + } + + #endregion + + #region PublicMethod + + /// + /// 列表. + /// + /// + [NonAction] + public async Task> GetList() + { + return await _repository.AsSugarClient().Queryable( + (a, b, c, d, e) => new JoinQueryInfos( + JoinType.Left, a.CreatorUserId == b.Id, + JoinType.Left, a.LastModifyUserId == c.Id, + JoinType.Left, a.DbType == d.EnCode && d.DeleteMark == null, + JoinType.Left, d.DictionaryTypeId == e.Id && e.EnCode == "dbType")) + .Where((a, b, c) => a.DeleteMark == null) + .OrderBy((a, b, c) => a.SortCode).OrderBy((a, b, c) => a.CreatorTime, OrderByType.Desc). + Select((a, b, c, d) => new DbLinkListOutput() { - output.Add(new DbLinkSelectorOutput() - { - id = item.Id, - fullName = item.FullName - }); - } - } + id = a.Id, + parentId = d.Id == null ? "-1" : d.Id, + creatorTime = a.CreatorTime, + creatorUser = SqlFunc.MergeString(b.RealName, "/", b.Account), + dbType = a.DbType, + enabledMark = a.EnabledMark, + fullName = a.FullName, + host = a.Host, + lastModifyTime = a.LastModifyTime, + lastModifyUser = SqlFunc.MergeString(c.RealName, "/", c.Account), + port = SqlFunc.ToString(a.Port), + sortCode = a.SortCode + }).Distinct().ToListAsync(); + } - return new { list = output.Union(data).ToList().ToTree() }; - } - - /// - /// 信息. - /// - /// 主键值. - /// - [HttpGet("{id}")] - public async Task GetInfo_Api(string id) + /// + /// 信息. + /// + /// 主键值. + /// + [NonAction] + public async Task GetInfo(string id) + { + var model = await _memCache.GetOrCreateAsync($"DbLink_{id}", async entry => { - var data = await GetInfo(id); - var oracleParam = data.OracleParam?.ToObject(); - var output = data.Adapt(); - if (oracleParam.IsNotEmptyOrNull() && oracleParam.oracleExtend) - { - output.oracleService = oracleParam.oracleService; - output.oracleExtend = oracleParam.oracleExtend; - output.oracleLinkType = oracleParam.oracleLinkType; - output.oracleRole = oracleParam.oracleRole; - } - - return output; - } - #endregion - - #region POST - - /// - /// 删除. - /// - /// 主键值. - /// - [HttpDelete("{id}")] - public async Task Delete(string id) - { - var entity = await GetInfo(id); - _ = entity ?? throw Oops.Oh(ErrorCode.COM1005); - var isOk = await _repository.AsUpdateable(entity).CallEntityMethod(m => m.Delete()).UpdateColumns(it => new { it.DeleteMark, it.DeleteTime, it.DeleteUserId }).ExecuteCommandHasChangeAsync(); - if (!isOk) - throw Oops.Oh(ErrorCode.COM1002); - } - - /// - /// 创建. - /// - /// 实体对象. - /// - [HttpPost("")] - public async Task Create_Api([FromBody] DbLinkCrInput input) - { - if (await _repository.IsAnyAsync(x => x.FullName == input.fullName && x.DeleteMark == null)) - throw Oops.Oh(ErrorCode.COM1004); - var entity = input.Adapt(); - if (input.oracleExtend) - { - entity.OracleParam = new OracleParamModel() - { - oracleExtend = input.oracleExtend, - oracleRole = input.oracleRole, - oracleLinkType = input.oracleLinkType, - oracleService = input.oracleService - }.ToJsonString(); - } - - var isOk = await _repository.AsInsertable(entity).IgnoreColumns(ignoreNullColumn: true).CallEntityMethod(m => m.Creator()).ExecuteCommandAsync(); - if (isOk < 1) - throw Oops.Oh(ErrorCode.COM1000); - } - - /// - /// 编辑. - /// - /// 主键值. - /// 实体对象. - /// - [HttpPut("{id}")] - public async Task Update_Api(string id, [FromBody] DbLinkUpInput input) - { - if (await _repository.IsAnyAsync(x => x.Id != id && x.FullName == input.fullName && x.DeleteMark == null)) - throw Oops.Oh(ErrorCode.COM1004); - var entity = input.Adapt(); - if (input.oracleExtend) - { - entity.OracleParam = new OracleParamModel() - { - oracleExtend = input.oracleExtend, - oracleRole = input.oracleRole, - oracleLinkType = input.oracleLinkType, - oracleService = input.oracleService - }.ToJsonString(); - } - - var isOk = await _repository.AsUpdateable(entity).IgnoreColumns(ignoreAllNullColumns: true).CallEntityMethod(m => m.LastModify()).ExecuteCommandHasChangeAsync(); - if (!isOk) - throw Oops.Oh(ErrorCode.COM1001); - } - - /// - /// 测试连接. - /// - /// 实体对象. - [HttpPost("Actions/Test")] - public void TestDbConnection([FromBody] DbLinkActionsTestInput input) - { - var entity = input.Adapt(); - entity.Id = input.id.Equals("0") ? SnowflakeIdHelper.NextId() : input.id; - if (input.oracleExtend) - { - entity.OracleParam = new OracleParamModel() - { - oracleExtend = input.oracleExtend, - oracleRole = input.oracleRole, - oracleLinkType = input.oracleLinkType, - oracleService = input.oracleService - }.ToJsonString(); - } - - if (!_dataBaseManager.IsConnection(entity)) - throw Oops.Oh(ErrorCode.D1507); - } - - #endregion - - #region PublicMethod - - /// - /// 列表. - /// - /// - [NonAction] - public async Task> GetList() - { - return await _repository.AsSugarClient().Queryable( - (a, b, c, d, e) => new JoinQueryInfos( - JoinType.Left, a.CreatorUserId == b.Id, - JoinType.Left, a.LastModifyUserId == c.Id, - JoinType.Left, a.DbType == d.EnCode && d.DeleteMark == null, - JoinType.Left, d.DictionaryTypeId == e.Id && e.EnCode == "dbType")) - .Where((a, b, c) => a.DeleteMark == null) - .OrderBy((a, b, c) => a.SortCode).OrderBy((a, b, c) => a.CreatorTime, OrderByType.Desc). - Select((a, b, c, d) => new DbLinkListOutput() - { - id = a.Id, - parentId = d.Id == null ? "-1" : d.Id, - creatorTime = a.CreatorTime, - creatorUser = SqlFunc.MergeString(b.RealName, "/", b.Account), - dbType = a.DbType, - enabledMark = a.EnabledMark, - fullName = a.FullName, - host = a.Host, - lastModifyTime = a.LastModifyTime, - lastModifyUser = SqlFunc.MergeString(c.RealName, "/", c.Account), - port = SqlFunc.ToString(a.Port), - sortCode = a.SortCode - }).Distinct().ToListAsync(); - } - - /// - /// 信息. - /// - /// 主键值. - /// - [NonAction] - public async Task GetInfo(string id) - { - return await _repository.GetFirstAsync(m => m.Id == id && m.DeleteMark == null); - } - #endregion + //entry.AbsoluteExpiration = DateTime.Now.AddMinutes(60); + entry.SlidingExpiration = TimeSpan.FromSeconds(60); + return await _repository.GetFirstAsync(m => m.Id == id && m.DeleteMark == null); + }); + return model; + } + #endregion } \ No newline at end of file diff --git a/visualdev/Tnb.VisualDev.Engine/Core/FormDataParsing.cs b/visualdev/Tnb.VisualDev.Engine/Core/FormDataParsing.cs index b8ad9c42..06bc0455 100644 --- a/visualdev/Tnb.VisualDev.Engine/Core/FormDataParsing.cs +++ b/visualdev/Tnb.VisualDev.Engine/Core/FormDataParsing.cs @@ -22,6 +22,7 @@ using JNPF.VisualDev.Entitys.Dto.VisualDevModelData; using JNPF.VisualDev.Interfaces; using JNPF.WorkFlow.Entitys.Entity; using Mapster; +using Microsoft.Extensions.Caching.Memory; using Newtonsoft.Json.Linq; using SqlSugar; @@ -54,44 +55,51 @@ public class FormDataParsing : ITransient /// private readonly ICacheManager _cacheManager; - /// - /// 服务基础仓储. - /// - private readonly ISqlSugarRepository _db; + /// + /// 缓存管理. + /// + private readonly IMemoryCache _memCache; - /// - /// 构造. - /// - /// - /// - /// - /// - /// - public FormDataParsing( - IUserManager userManager, - ICacheManager cacheManager, - IDataBaseManager databaseService, - IDataInterfaceService dataInterfaceService, - ISqlSugarRepository context) - { - _userManager = userManager; - _cacheManager = cacheManager; - _databaseService = databaseService; - _dataInterfaceService = dataInterfaceService; - _db = context; - } - #endregion + /// + /// 服务基础仓储. + /// + private readonly ISqlSugarRepository _db; - #region 解析模板数据 + /// + /// 构造. + /// + /// + /// + /// + /// + /// + public FormDataParsing( + IUserManager userManager, + ICacheManager cacheManager, + IDataBaseManager databaseService, + IDataInterfaceService dataInterfaceService, + ISqlSugarRepository context, + IMemoryCache memCache) + { + _userManager = userManager; + _cacheManager = cacheManager; + _databaseService = databaseService; + _dataInterfaceService = dataInterfaceService; + _db = context; + _memCache = memCache; + } + #endregion - /// - /// 控制模板数据转换. - /// - /// 数据. - /// 数据模板. - /// 操作类型(List-列表值,create-创建值,update-更新值,detail-详情值,transition-过渡值,query-查询). - /// object. - public object TemplateControlsDataConversion(object data, FieldsModel fieldsModel, string? actionType = null) + #region 解析模板数据 + + /// + /// 控制模板数据转换. + /// + /// 数据. + /// 数据模板. + /// 操作类型(List-列表值,create-创建值,update-更新值,detail-详情值,transition-过渡值,query-查询). + /// object. + public object TemplateControlsDataConversion(object data, FieldsModel fieldsModel, string? actionType = null) { if (fieldsModel == null || data == null || data.Equals("[]") || data.ToString().Equals("[]") || string.IsNullOrEmpty(data.ToString())) return string.Empty; try @@ -1707,18 +1715,30 @@ public class FormDataParsing : ITransient } break; case JnpfKeyConst.CURRDEPT: - dataMap[key] = (await _db.AsSugarClient().Queryable().FirstAsync(x => x.Id == dataValue.ToString()))?.FullName; + dataMap[key] = await _memCache.GetOrCreateAsync($"organizeId_{dataValue}", async entry => + { + entry.SlidingExpiration = TimeSpan.FromSeconds(60); + return (await _db.AsSugarClient().Queryable().FirstAsync(x => x.Id == dataValue.ToString()))?.FullName; + }); break; case JnpfKeyConst.MODIFYUSER: case JnpfKeyConst.CREATEUSER: - dataMap[key] = await _db.AsSugarClient().Queryable().Where(x => x.Id == dataValue.ToString()).Select(x => SqlFunc.MergeString(x.RealName, "/", x.Account)).FirstAsync(); + dataMap[key] = await _memCache.GetOrCreateAsync($"userId_{dataValue}", async entry => + { + entry.SlidingExpiration = TimeSpan.FromSeconds(60); + return await _db.AsSugarClient().Queryable().Where(x => x.Id == dataValue.ToString()).Select(x => SqlFunc.MergeString(x.RealName, "/", x.Account)).FirstAsync(); + }); break; case JnpfKeyConst.MODIFYTIME: case JnpfKeyConst.CREATETIME: dataMap[key] = string.Format("{0:yyyy-MM-dd HH:mm:ss}", dataMap[key].ToString().ParseToDateTime()); break; case JnpfKeyConst.CURRPOSITION: - dataMap[key] = (await _db.AsSugarClient().Queryable().FirstAsync(x => x.Id == dataValue.ToString()))?.FullName; + dataMap[key] = await _memCache.GetOrCreateAsync($"positionId_{dataValue}", async entry => + { + entry.SlidingExpiration = TimeSpan.FromSeconds(60); + return (await _db.AsSugarClient().Queryable().FirstAsync(x => x.Id == dataValue.ToString()))?.FullName; + }); break; case JnpfKeyConst.POPUPTABLESELECT: case JnpfKeyConst.POPUPSELECT: diff --git a/visualdev/Tnb.VisualDev/RunService.cs b/visualdev/Tnb.VisualDev/RunService.cs index 6d3fcfb0..75cd7cdf 100644 --- a/visualdev/Tnb.VisualDev/RunService.cs +++ b/visualdev/Tnb.VisualDev/RunService.cs @@ -205,7 +205,8 @@ public class RunService : IRunService, ITransient { if (templateInfo.SingleFormData.Any(x => x.__config__.templateJson != null && x.__config__.templateJson.Any())) realList.list = await _formDataParsing.GetKeyData(templateInfo.SingleFormData.Where(x => x.__config__.templateJson != null && x.__config__.templateJson.Any()).ToList(), realList.list, templateInfo.ColumnData, actionType, templateInfo.WebType, primaryKey); - realList.list = await _formDataParsing.GetKeyData(templateInfo.SingleFormData.Where(x => x.__config__.templateJson == null).ToList(), realList.list, templateInfo.ColumnData, actionType, templateInfo.WebType, primaryKey); + else + realList.list = await _formDataParsing.GetKeyData(templateInfo.SingleFormData.Where(x => x.__config__.templateJson == null).ToList(), realList.list, templateInfo.ColumnData, actionType, templateInfo.WebType, primaryKey); // 如果是无表数据并且排序字段不为空,再进行数据排序 if (!templateInfo.IsHasTable && input.sidx.IsNotEmptyOrNull())