返回 SQL 数据集后,EF Core HTML Table 呈现速度非常慢
EF Core HTML Table render very slow after SQL Dataset is returned
我有一个 Linq 查询通过 EF Core(通过 VPN)在 900 - 919 毫秒内返回数据。然而,一旦返回数据,它就需要一段时间(20-30 秒)来呈现 HTML table。该数据集大约有 18,000 行和 8 列,我已经实现了 DataTables 来分页、过滤和导出。数据集本身仅包含文本。
我一直在尝试分析那 20-30 秒,但没有取得太大成功,我似乎找不到问题的根源。
有没有人遇到过类似的问题?
谁能推荐一种好的调试方法来了解延迟的原因?
我启用了日志记录,但这并没有告诉我任何有用的信息,我无法使用 VS 中的 Application Insights。
非常感谢。
更新
方法如下
public async Task<ActionResult> ExportGrid()
{
var result = await dbcontext.Timesheet.AsNoTracking()//.Take(100)
//.Include(t => t.Program)
//.ThenInclude(p => p.Client)
//.Include(t => t.Task)
//.Include(t => t.Person)
.Where(t => !t.Deleted)
.Select(t => new TimesheetDataViewModel
{
Id = t.Id,
ClientName = t.Program.Client.Name,
ProgramName = t.Program.Name,
TaskType = t.Task.Name,
TaskName = t.Name,
TaskDescription = t.Description,
TaskStart = t.TaskStart,
TaskEnd = t.TaskEnd,
Minutes = t.Minutes,
Person = t.Person.Firstname + ' ' + t.Person.Surname
}).ToListAsync();
return View(result);
}
下面是数据表代码
var _tableId = $('#datatable_timesheet');
var _orderColumns = [1];
var _searchableColumns = [0,1,2];
var _defaultSort = [1, "asc"];
$(document).ready(function () {
_tableId.DataTable({
paging: true,
ordering: true,
info: false,
responsive: true,
deferRender: false,
dom: '<"row"<"col-sm-3"l><"col-sm-6 text-center"B"><"col-sm-3"f>><"row"<"col-sm-12"tr>><"row"<"col-sm-5"i><"col-sm-7"p>>',
buttons: true,
lengthMenu: [
[5, 15, 20, -1],
[5, 15, 20, "All"] // change per page values here
],
//pagingType: "bootstrap_full_number",
language: {
"lengthMenu": " _MENU_ records",
"paginate": {
"previous": "Prev",
"next": "Next",
"last": "Last",
"first": "First"
}
},
columnDefs: [{ // set default column settings
'orderable': true,
'targets': _orderColumns
}, {
"searchable": true,
"targets": _searchableColumns
}]
//order: _defaultSort // set first column as a default sort by asc*/
});
});
它将在客户端分页
为了获得更好的性能,您可以使用服务器端分页 - 例如参考文章使用服务器端分页。
https://www.codeproject.com/Tips/1011531/Using-jQuery-DataTables-with-Server-Side-Processin
我发现这很难让我头脑清醒,以防万一其他人,下面是我最终如何让一切正常工作,但对使用 .Net Core 1.1 和 Entity.Framework.Core[=13 构建的应用程序进行排序除外=]
HTML
<table class="table table-striped table-bordered table-hover" id="exportGrid">
<thead>
<tr>
<th>
Client Name
</th>
<th>
Program Name
</th>
<th>
Person
</th>
<th>
Minutes
</th>
<th>
Task Name
</th>
<th>
Task Description
</th>
<th>
Task Type
</th>
<th>
Task Start
</th>
<th>
Task End
</th>
</tr>
</thead>
</table>
JS 和 AJAX
$('#exportGrid').DataTable({
processing: true,
serverSide: true,
ajax: { "url": "TimesheetDataJsonObjectArray", "type": "POST" },
columns: [
{ "data": "clientName" },
{ "data": "programName" },
{ "data": "person" },
{ "data": "minutes" },
{ "data": "taskName" },
{ "data": "taskDescription" },
{ "data": "taskType" },
{ "data": "taskStart" },
{ "data": "taskEnd" }],
pageLength: 15,
paging: true,
ordering: true,
info: true,
responsive: true,
deferRender: false,
dom: '<"row"<"col-sm-3"l><"col-sm-6 text-center"B"><"col-sm-3"f>><"row"<"col-sm-12"tr>><"row"<"col-sm-5"i><"col-sm-7"p>>',
buttons: true,
lengthMenu: [
[5, 15, 20, -1],
[5, 15, 20, "All"]
]
});
控制器
[HttpPost]
public async Task<ActionResult> TimesheetDataJsonObjectArray(int draw, int start, int length)
{
var formData = HttpContext.Request.Form;
string search = formData["search[value]"];
var q = dbcontext.Timesheet.Where(t => !t.Deleted);
if(!String.IsNullOrEmpty(search))
{
q = q.Where(t => t.Person.Surname.Contains(search));
}
var b = await q
.Select(t => new TimesheetDataViewModel
{
Id = t.Id,
ClientName = t.Program.Client.Name,
ProgramName = t.Program.Name,
TaskType = t.Task.Name,
TaskName = t.Name,
TaskDescription = t.Description,
TaskStart = t.TaskStart,
TaskEnd = t.TaskEnd,
Minutes = t.Minutes,
Person = t.Person.Firstname + ' ' + t.Person.Surname
}).ToListAsync();
var result = b.Skip(start).Take(length);
DataTableData a = new DataTableData();
a.data = result.ToList();
a.draw = draw;
a.recordsTotal = q.Count();
a.recordsFiltered = q.Count();
return Json(a);
}
我有一个 Linq 查询通过 EF Core(通过 VPN)在 900 - 919 毫秒内返回数据。然而,一旦返回数据,它就需要一段时间(20-30 秒)来呈现 HTML table。该数据集大约有 18,000 行和 8 列,我已经实现了 DataTables 来分页、过滤和导出。数据集本身仅包含文本。
我一直在尝试分析那 20-30 秒,但没有取得太大成功,我似乎找不到问题的根源。
有没有人遇到过类似的问题?
谁能推荐一种好的调试方法来了解延迟的原因?
我启用了日志记录,但这并没有告诉我任何有用的信息,我无法使用 VS 中的 Application Insights。
非常感谢。
更新
方法如下
public async Task<ActionResult> ExportGrid()
{
var result = await dbcontext.Timesheet.AsNoTracking()//.Take(100)
//.Include(t => t.Program)
//.ThenInclude(p => p.Client)
//.Include(t => t.Task)
//.Include(t => t.Person)
.Where(t => !t.Deleted)
.Select(t => new TimesheetDataViewModel
{
Id = t.Id,
ClientName = t.Program.Client.Name,
ProgramName = t.Program.Name,
TaskType = t.Task.Name,
TaskName = t.Name,
TaskDescription = t.Description,
TaskStart = t.TaskStart,
TaskEnd = t.TaskEnd,
Minutes = t.Minutes,
Person = t.Person.Firstname + ' ' + t.Person.Surname
}).ToListAsync();
return View(result);
}
下面是数据表代码
var _tableId = $('#datatable_timesheet');
var _orderColumns = [1];
var _searchableColumns = [0,1,2];
var _defaultSort = [1, "asc"];
$(document).ready(function () {
_tableId.DataTable({
paging: true,
ordering: true,
info: false,
responsive: true,
deferRender: false,
dom: '<"row"<"col-sm-3"l><"col-sm-6 text-center"B"><"col-sm-3"f>><"row"<"col-sm-12"tr>><"row"<"col-sm-5"i><"col-sm-7"p>>',
buttons: true,
lengthMenu: [
[5, 15, 20, -1],
[5, 15, 20, "All"] // change per page values here
],
//pagingType: "bootstrap_full_number",
language: {
"lengthMenu": " _MENU_ records",
"paginate": {
"previous": "Prev",
"next": "Next",
"last": "Last",
"first": "First"
}
},
columnDefs: [{ // set default column settings
'orderable': true,
'targets': _orderColumns
}, {
"searchable": true,
"targets": _searchableColumns
}]
//order: _defaultSort // set first column as a default sort by asc*/
});
});
它将在客户端分页 为了获得更好的性能,您可以使用服务器端分页 - 例如参考文章使用服务器端分页。
https://www.codeproject.com/Tips/1011531/Using-jQuery-DataTables-with-Server-Side-Processin
我发现这很难让我头脑清醒,以防万一其他人,下面是我最终如何让一切正常工作,但对使用 .Net Core 1.1 和 Entity.Framework.Core[=13 构建的应用程序进行排序除外=]
HTML
<table class="table table-striped table-bordered table-hover" id="exportGrid">
<thead>
<tr>
<th>
Client Name
</th>
<th>
Program Name
</th>
<th>
Person
</th>
<th>
Minutes
</th>
<th>
Task Name
</th>
<th>
Task Description
</th>
<th>
Task Type
</th>
<th>
Task Start
</th>
<th>
Task End
</th>
</tr>
</thead>
</table>
JS 和 AJAX
$('#exportGrid').DataTable({
processing: true,
serverSide: true,
ajax: { "url": "TimesheetDataJsonObjectArray", "type": "POST" },
columns: [
{ "data": "clientName" },
{ "data": "programName" },
{ "data": "person" },
{ "data": "minutes" },
{ "data": "taskName" },
{ "data": "taskDescription" },
{ "data": "taskType" },
{ "data": "taskStart" },
{ "data": "taskEnd" }],
pageLength: 15,
paging: true,
ordering: true,
info: true,
responsive: true,
deferRender: false,
dom: '<"row"<"col-sm-3"l><"col-sm-6 text-center"B"><"col-sm-3"f>><"row"<"col-sm-12"tr>><"row"<"col-sm-5"i><"col-sm-7"p>>',
buttons: true,
lengthMenu: [
[5, 15, 20, -1],
[5, 15, 20, "All"]
]
});
控制器
[HttpPost]
public async Task<ActionResult> TimesheetDataJsonObjectArray(int draw, int start, int length)
{
var formData = HttpContext.Request.Form;
string search = formData["search[value]"];
var q = dbcontext.Timesheet.Where(t => !t.Deleted);
if(!String.IsNullOrEmpty(search))
{
q = q.Where(t => t.Person.Surname.Contains(search));
}
var b = await q
.Select(t => new TimesheetDataViewModel
{
Id = t.Id,
ClientName = t.Program.Client.Name,
ProgramName = t.Program.Name,
TaskType = t.Task.Name,
TaskName = t.Name,
TaskDescription = t.Description,
TaskStart = t.TaskStart,
TaskEnd = t.TaskEnd,
Minutes = t.Minutes,
Person = t.Person.Firstname + ' ' + t.Person.Surname
}).ToListAsync();
var result = b.Skip(start).Take(length);
DataTableData a = new DataTableData();
a.data = result.ToList();
a.draw = draw;
a.recordsTotal = q.Count();
a.recordsFiltered = q.Count();
return Json(a);
}