简体   繁体   English

jQuery DataTable和MVC服务器端处理

[英]jQuery DataTable and MVC server side processing

So I have implemented Server-Side processing in MVC for jQuery Datatables, I am Showing 1 to 10 of 8,037 entries (with pagination). 因此,我已经在MVC中为jQuery数据表实现了服务器端处理,我正在显示1 to 10 of 8,037 entries (带有分页)。 However when I navigate to the page with the table the first load takes far to long (5 to 10 seconds). 但是,当我导航到带有表的页面时,第一次加载要花费很长时间(5到10秒)。 In my controller I set it to only take 10 records (iDisplayLength) : 在我的控制器中,我将其设置为仅记录10条记录(iDisplayLength)

        var displayedProviders = filteredProviders
            .Skip(param.iDisplayStart)
            .Take(param.iDisplayLength);

So when I first navigate to the page with the table or I use pagination it should only load 10 records at a time. 因此,当我第一次导航到带有表的页面或使用分页时,一次只能加载10条记录。

Can anyone guide me to why the first load is taking such a long time? 谁能指导我为什么第一次加载要花这么长时间? My fear is that its loading the entire table into the Json Request which is slowing it down at first. 我担心它会将整个表加载到Json Request中,这一开始会减慢它的速度。 This wasnt what I had in mind when implementing server side processing. 这不是我在实现服务器端处理时所想到的。 Is there a way around this? 有没有解决的办法? If I implement: 如果我实施:

    var model = _db.CareProviders
.OrderBy(row => row.ProviderId).Skip((pageNumber - 1) * pageResults)
    .Take(pageResults).ToList();

This will only show 10 results and no more? 这只会显示10个结果,不会更多?

Model: 模型:

    public class jQueryDataTableParamModel
    {
        /// <summary>
        /// Request sequence number sent by DataTable,
        /// same value must be returned in response
        /// </summary>       
        public string sEcho { get; set; }

        /// <summary>
        /// Text used for filtering
        /// </summary>
        public string sSearch { get; set; }

        /// <summary>
        /// Number of records that should be shown in table
        /// </summary>
        public int iDisplayLength { get; set; }

        /// <summary>
        /// First record that should be shown(used for paging)
        /// </summary>
        public int iDisplayStart { get; set; }

        /// <summary>
        /// Number of columns in table
        /// </summary>
        public int iColumns { get; set; }

        /// <summary>
        /// Number of columns that are used in sorting
        /// </summary>
        public int iSortingCols { get; set; }

        /// <summary>
        /// Comma separated list of column names
        /// </summary>
        public string sColumns { get; set; }
    }
}

Controller: 控制器:

    public ActionResult AjaxHandler(jQueryDataTableParamModel param)
    {
        var allProviders = _db.CareProviders.ToList();
        IEnumerable<CareProvider> filteredProviders;

        if (!string.IsNullOrEmpty(param.sSearch))
        {
            filteredProviders = _db.CareProviders.ToList()
                     .Where(c => c.ProviderId.Contains(param.sSearch)
                                 ||
                      c.CareServiceType.Contains(param.sSearch)
                                 ||
                                 c.CareServiceName.Contains(param.sSearch));
        }
        else
        {
            filteredProviders = allProviders;
        }
        var displayedProviders = filteredProviders
            .Skip(param.iDisplayStart)
            .Take(param.iDisplayLength);

        var result = from c in displayedProviders
                     select new[] { Convert.ToString(c.ProviderId), c.CareServiceType, c.CareServiceName, c.Email };
        return Json(new
        {
            sEcho = param.sEcho,
            iTotalRecords = allProviders.Count(),
            iTotalDisplayRecords = filteredProviders.Count(),
            aaData = result
        },
                         JsonRequestBehavior.AllowGet);

    }

Jquery DataTable Script: jQuery DataTable脚本:

<script type="text/javascript">
    $(function () {
        // Initialize Example 2
        // $('#example2').dataTable();
        $('#example2').dataTable({
            "bServerSide": true,
            "sAjaxSource": "AdminPanel/AjaxHandler",
            "bProcessing": true,
            "aoColumns": [
                            { "sName": "ProviderId" },
                            { "sName": "CareServiceType" },
                            { "sName": "CareServiceName" },
                            { "sName": "Email" }
            ]
        });
    });
</script>

I don't believe this is a datatables problem. 我不认为这是数据表问题。 In your code, the first line var allProviders = _db.CareProviders.ToList(); 在您的代码中,第一行var allProviders = _db.CareProviders.ToList(); is immediately hitting your database and loading all of your providers into memory. 立即访问您的数据库并将所有提供程序加载到内存中。 Only after loading into memory are you then filtering with skip and take, so you are hitting the initial query execution overhead. 只有在加载到内存中之后,您才可以使用“跳过”和“获取”进行过滤,因此您要承担初始查询执行的开销。 To make things a little worse, if you have a filtering condition, you run filteredProviders = _db.CareProviders.ToList() which hits your database and does the whole thing over again. 更糟糕的是,如果您有过滤条件,请运行filteredProviders = _db.CareProviders.ToList() ,它会打入数据库并重新进行整个操作。

Remember while linq employs deferred execution, calling ToList() tells it "OK, I want this now." 请记住,当linq使用延迟执行时,调用ToList()告诉它“确定,我现在ToList() ”。 It stops building your expression trees, hits your database, and dumps the result into your list, and any further filtering is done on the list itself. 它停止构建表达式树,访问数据库,并将结果转储到列表中,并且进一步的过滤都在列表本身上进行。

Your initial premise is correct. 您的最初前提是正确的。 running var model = _db.CareProviders .OrderBy(row => row.ProviderId).Skip((pageNumber - 1) * pageResults) .Take(pageResults).ToList(); 运行var model = _db.CareProviders .OrderBy(row => row.ProviderId).Skip((pageNumber - 1) * pageResults) .Take(pageResults).ToList(); will indeed only return the rows you want, as long as you are using a provider that understands skip and take (EF does). 只要您使用的是理解跳过和采用的提供程序(EF会这样做),它的确只会返回所需的行。

Consolidate your allProviders and filteredProviders variables, and call ToList() only after you've applied all possible filters and your skip and take, and see if that improves your speed. 合并allProvidersfilteredProviders变量,并仅在应用所有可能的过滤器并进行跳过和调用之后再调用ToList() ,看看是否可以提高速度。

In the first line of the AjaxHandler method, there is var allProviders = _db.CareProviders.ToList(); 在AjaxHandler方法的第一行中,有var allProviders = _db.CareProviders.ToList(); which will load everything from the table. 它将加载表格中的所有内容。 Is it the large one? 是大的吗? ... If so, that is your problem. ...如果是这样,那是您的问题。

Also the line filteredProviders = _db.CareProviders.ToList() will load everything from the table and materialize that. 同样, filteredProviders = _db.CareProviders.ToList()行将加载表中的所有内容并将其具体化。 The Where will be executed on the materialized data and also the Take method later in the code will take the small portion from already materialized data (the same reason). 将在实例化数据上执行Where并且稍后代码中的Take方法将从已经实例化的数据中提取一小部分(相同的原因)。

It is the selection from the DB and the materialization what is taking a long time. 从数据库和实现中选择是要花费很长时间的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM