ASP.NET中KTDatatable日期列排序异常问题求助
KTDatatable日期列排序异常问题解决
问题描述
开发ASP.NET Web应用时,使用KTDatatable展示数据,首次访问应用时数据显示正常,但对「Date Creation」列进行升序/降序排序后,结果与Oracle数据库的排序逻辑不匹配。
相关代码
LISTFACT.cshtml(视图)
var demo = function () { datatable = $('#json_data').KTDatatable({ // datasource definition data: { type: 'remote', source: '/FactureCLIENT/GETLIST_FACTURE', pageSize: 10, }, // layout definition layout: { scroll: false, // enable/disable datatable scroll both horizontal and vertical when needed. footer: true // display/hide footer }, sortable: true, height: 300, pagination: true, footer: false, // columns definition columns: [ { field: 'NUM_FAC', title: 'NUM Facture', }, { field: 'RaisonSocial', title: 'Raison Social', }, { field: 'DATE_CRE', title: 'Date Creation', }, { field: 'Actions', title: 'Actions', sortable: false, width: 110, autoHide: false, overflow: 'visible', template: function (row) { return '\ <div class="dropdown">\ <a href="javascript:;" class="btn btn-sm btn-clean btn-icon btn-icon-md" data-toggle="dropdown">\ <i class="la la-cog"></i>\ </a>\ <div class="dropdown-menu dropdown-menu-right">\ <a class="dropdown-item" href="javascript:void(0);" class="btn btn-sm btn-clean btn-icon btn-icon-md" id="Download" data-id=' + row.NUM_FAC + '><i class="la la-print"></i> Download PDF</a>\ <a class="dropdown-item" href="javascript:void(0);" class="btn btn-sm btn-clean btn-icon btn-icon-md" id="DownloadEXL" data-id=' + row.NUM_FAC + '><i class="la la-print"></i> Download Excel</a>\ </div>\ </div>\ <a href="javascript:void(0);" class="btn btn-sm btn-clean btn-icon btn-icon-md" id="Supprimer" title="Supprimer" data-id=' + row.NUM_FAC + '>\ <i class="la la-trash"></i>\ </a>\ <a href="javascript:void(0);" class="btn btn-sm btn-clean btn-icon btn-icon-md" id="Edite" title="Edite" data-id=' + row.NUM_FAC + '>\ <i class="la la-edit"></i>\ </a>\ '; }, }], }); };
Controller.cs(控制器)
public ActionResult GETLIST_FACTURE() { LIST_ENT_FAC model = new LIST_ENT_FAC(); model.GetFACTUR_LIST(MY_CON); return new CustomJsonResult() { Data = (model.List_FAC) }; }
Model.cs(模型)
public class LIST_ENT_FAC { public List<ENT_FACTURE_CLIENT> List_FAC { get; set; } internal void GetFACTUR_LIST(OracleConnection mY_CON) { this.List_FAC = new List<ENT_FACTURE_CLIENT>(); OracleCommand cmd = new OracleCommand("select Z_VTL_FAC_CLI_ENT.NUM_FAC ,Z_VTL_FAC_CLI_ENT.\"rais_soc\" , Z_VTL_FAC_CLI_ENT.DAT_CRE from Z_VTL_FAC_CLI_ENT order by DAT_CRE desc", mY_CON); mY_CON.Open(); OracleDataReader read = cmd.ExecuteReader(); while (read.Read()) { this.List_FAC.Add(new ENT_FACTURE_CLIENT { NUM_FAC = read.GetString(0), RaisonSocial = read.GetString(1), DATE_CRE = read.GetDateTime(2), TEXT_DATE_CRE = read.GetDateTime(2).ToString() }); } read.Close(); mY_CON.Close(); } }
问题原因
当前实现中,KTDatatable默认对返回的日期数据执行客户端排序,但日期序列化为JSON后会转换为字符串格式,前端按字符串字典序排序,而非日期逻辑排序,导致与数据库的排序结果不一致;同时后端仅在首次加载时按DAT_CRE desc排序,前端触发排序时并未请求数据库重新排序,而是在本地对数据进行处理。
解决方案
方案一:后端接收排序参数,数据库层面执行排序(推荐,适合大数据量场景)
通过让KTDatatable传递排序字段和方向参数,后端动态生成排序SQL,让数据库执行排序逻辑,确保结果与数据库一致。
- 修改控制器,接收排序参数
public ActionResult GETLIST_FACTURE(string sortField, string sortDir) { LIST_ENT_FAC model = new LIST_ENT_FAC(); // 设置默认排序规则 if (string.IsNullOrEmpty(sortField)) { sortField = "DAT_CRE"; sortDir = "desc"; } model.GetFACTUR_LIST(MY_CON, sortField, sortDir); return new CustomJsonResult() { Data = model.List_FAC }; }
- 修改模型,动态生成排序SQL(添加字段白名单校验防SQL注入)
internal void GetFACTUR_LIST(OracleConnection mY_CON, string sortField, string sortDir) { this.List_FAC = new List<ENT_FACTURE_CLIENT>(); // 字段白名单,防止SQL注入 var allowedFields = new List<string> { "NUM_FAC", "rais_soc", "DAT_CRE" }; if (!allowedFields.Contains(sortField)) { sortField = "DAT_CRE"; } // 校验排序方向,默认降序 sortDir = sortDir.Equals("asc", StringComparison.OrdinalIgnoreCase) ? "asc" : "desc"; string sql = $"select Z_VTL_FAC_CLI_ENT.NUM_FAC, Z_VTL_FAC_CLI_ENT.\"rais_soc\", Z_VTL_FAC_CLI_ENT.DAT_CRE from Z_VTL_FAC_CLI_ENT order by {sortField} {sortDir}"; OracleCommand cmd = new OracleCommand(sql, mY_CON); mY_CON.Open(); OracleDataReader read = cmd.ExecuteReader(); while (read.Read()) { this.List_FAC.Add(new ENT_FACTURE_CLIENT { NUM_FAC = read.GetString(0), RaisonSocial = read.GetString(1), DATE_CRE = read.GetDateTime(2), TEXT_DATE_CRE = read.GetDateTime(2).ToString() }); } read.Close(); mY_CON.Close(); }
- 修改视图,让KTDatatable传递排序参数
data: { type: 'remote', source: function (query) { return { url: '/FactureCLIENT/GETLIST_FACTURE', params: { sortField: query.sort.field, sortDir: query.sort.dir } }; }, pageSize: 10, },
方案二:前端配置日期类型,按日期逻辑排序(适合小数据量场景)
在KTDatatable的列定义中指定字段类型为date,并匹配后端返回的日期格式,让前端识别为日期对象后再排序。
修改视图中的列定义:
{ field: 'DATE_CRE', title: 'Date Creation', type: 'date', format: 'YYYY-MM-DD HH:mm:ss' // 需与后端返回的日期字符串格式完全匹配 },
内容的提问来源于stack exchange,提问作者Mohamed Tajouri
相关产品推荐
相关产品推荐

