【问题标题】:JQuery Datatables and .NET WebAPI Performance ConsiderationsJQuery 数据表和 .NET WebAPI 性能注意事项
【发布时间】:2016-07-21 03:03:31
【问题描述】:

我只是想就我在一个项目中所做的观察获得一些社区意见,该项目利用 JQuery 数据表来呈现将从设置 Web API 项目中提取数据的数据。

因此,考虑到将返回用户列表 (GetAllUsers) 的 Web API 控制器上的代码价格 - 使用存储库模式:

public List<SampleUser> GetAllUsers()
{
  return Uow.SampleUser.GetAll().toList();
}

将返回一个用户列表,其范围可以从 10 到 10000 条记录。

但是,根据观察,我们会在前端消费并处理返回的数据。这意味着分页、搜索、过滤和排序等任务是在客户端使用提到的插件(JQuery 数据表)处理的。

不管数据进入客户端的入口点是什么,无论是通过 Ajax 调用还是发送到 MVC 控制器,发送到客户端的数据基本上都是整组记录(其中可能有成百上千)在可能请求它的特定页面的每次加载上。

查看 JQuery 数据表的设置和初始化是重点,而且相当直接:

$(document).ready(function () {
        var table = $('#reportTable').DataTable({
            responsive: true,
            "bServerSide": false,
            "sAjaxSource": "GetRefugeeApplicant",
            "processing": false,
            "bFilter": true,
            "sDom": "lrtip"
        });

因此,分页任务、过滤、排序和搜索变得相当容易考虑。但是,问题出现在初始页面加载的性能上,因为随着数据表的增长,被拉下的记录数量也会增加。澄清一下,如果存在 1000 条用户记录,那么所有 1000 条用户都将被拉到客户端并导致初始调用的开销更大,因为诸如分页、搜索和过滤之类的任务不会调用服务器并正常工作在初始请求中提取了哪些数据。

因此,这里出现的问题变成了一个询问是否将所有数据加载到客户端并使用所述数据在客户端工作,或者调用处理分页的 API 是否可行任务服务器端基本上将固定数量的记录(例如 10 条)拉到客户端。像这样:

public IHttpActionResult GetAllPersons(Guid id, int page = 0, int pageSize = 0, string searchQuery = "", string orderBy = "")
        {
            var response = ResponseMessage(new HttpResponseMessage(HttpStatusCode.InternalServerError));
            var personList = new Person(Uow).GetAllPersons(searchQuery);
            if (personList == null) return response;
            var totalCount = personList.Count;
            var totalPages = (int)Math.Ceiling((double)totalCount / pageSize);

            switch (orderBy)
            {
                default:
                    personList = personList.OrderBy(c => c.PersonId).ToList();
                    break;
            }

            personList = personList
                .Skip(pageSize * page)
                .Take(pageSize)
                .ToList();

            var result = new
            {
                personList,
                pagingDetails = new
                {
                    totalPages,
                    totalCount,
                    prevLink = "",
                    nextLink = "",
                    currentCount = personList.Count
                }
            };

            var responseMessage = Request.CreateResponse(HttpStatusCode.OK, new JsonResponseObject
            {
                Data = result,
                Message = "Person Details Retrieved Successfully.",
                IsSuccessful = true
            });

            response = ResponseMessage(responseMessage);
            return response;
        }

但是,这种方法 (1) 无法与 JQuery Datatables 一起正常工作,因为它只会返回所需的行数,而不是通常需要“在内存中”使用的所有行。 (2) 使用这种方法意味着在每次寻呼调用时,取决于客户端,您必须访问服务器以执行查询任务。

所以我在这里有点分歧,至于哪个是最好的解决方案,如果我不得不在客户端使用 JQuery 数据表,除了那些我谈到了。

谢谢

【问题讨论】:

    标签: c# jquery asp.net-mvc asp.net-web-api datatables


    【解决方案1】:

    您不希望向您的客户端拉取比您在给定会话中使用的合理预期更多的数据。

    这种情况就是 OData 之类的东西旨在解决的问题。它提供了一种标准化的方式来处理客户端和 API 之间的数据排序、分页和过滤等事务。

    Web.API 具有用于 OData 的 support,许多 JavaScript 组件也是如此。

    【讨论】:

      【解决方案2】:

      绝对推荐实现服务器端分页和过滤。我完全像这样在 WebApi 上使用 Datatables,它的性能很好。

      但是,在您的示例中要注意一点:您实现 GetAllPersons 端点的方式,它将从内存中的数据库中读取所有记录:

      var personList = new Person(Uow).GetAllPersons(searchQuery);
      

      然后它会应用分页:

      personList = personList
                      .Skip(pageSize * page)
                      .Take(pageSize)
                      .ToList();
      

      这会更快一些,因为您没有将所有数据发送到客户端,但您应该将分页应用于查询,以便您仅从数据库中读取当前页面,并将记录总数请求为 Count。这可以在返回表和标量值的存储过程中完成,但将其映射到 EF 而不是“纯”存储库模式会稍微复杂一些。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-02-03
        • 2018-12-24
        • 2011-07-09
        • 2017-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多