返回 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);
    }