问题:
我在Angular JS html页面中使用了Kendo Grid。 Kendo Grid数据来自我的远程服务Web API。
Kendo网格尝试在浏览器中为每10条记录下载38 MB的内容,同时我们正在进行分页(或首次加载页面)并且需要大约。 6分钟加载数据。
下载38 MB的内容和内容是什么?
我已经通过阅读/学习堆栈溢出的类似支持票据来实现:
实施服务器分页为真(pageSize = 10,总记录数= 56000)
捆绑JS和CSS
我尝试了以下两个选项:
scrollable:{virtual:true} 要么 scrollable:{endless:true}
我在生产时检查我的存储过程,它在不到3秒的时间内执行。 55000条记录。 (在生产和暂存两台服务器上)。
我检查了我的Web API控制器,它在不到4秒的时间内将响应返回到kendo网格,然后kendo网格花费了太多时间来填充数据。
我有以下JS和CSS for Kendo(已实施捆绑):
以下是我的实时项目页面:
HTML页面:
<div id="heatMapGrid" kendo-grid k-options="vm.heatMapGridOptions"></div>
AngularJS控制器:
var dataSourceHeatMapGrid = new kendo.data.DataSource({
transport: {
read: function (options) {
heatMapService.getHeatMapGrid(options.data, heatMapGridParams)
.then(function (response) {
options.success(response.data);
$rootScope.optioncallback = options;
//$scope.htmapGridCSV = [];
//$scope.htmapGridCSV = response.data.exportData;
}).catch(function (e) {
console.log('Error: ', e);
throw e;
});
},
parameterMap: function (options) {
return JSON.stringify(options);
}
},
schema: {
data: function (response) {
return response.gridData;
},
total: function (response) {
return response.Total;
},
model: {
fields: {
TPID: { type: "number" },
TPName: { type: "string" },
EndCustomerPurchaseAmt: { type: "number" },
PrimaryExpirationMonth: { type: "string" },
AgreementID: { type: "number" },
TotalPurchased: { type: "number" },
TotalAssigned: { type: "number" },
OverUnder: { type: "number" },
VSEntPurchasedUnits: { type: "number" },
VSProMSDNUnits: { type: "number" },
VSTestProMSDNUnits: { type: "number" },
MSDNPlat: { type: "number" },
CloudPurchasedUnits: { type: "number" },
UnbilledOverage: { type: "number" },
AzurePotentialRevenue: { type: "number" }
}
}
},
pageSize: 10,
serverPaging: true
});
vm.heatMapGridOptions = {
columns: [
{ "title": "", template: "<a title='#=TPID#' #=isPinnedAccount==1 ? \"class='terrunpinaccount'\" : \"class='terrpinaccount'\"# ng-click='vm.pinUnpinAccount(\"#=TPID#\")'></a>" },
{ "title": "Account Name", "field": "TPName", template: "<a href='javascript:void(0);' ng-click='vm.tPIDDetails(\"#=TPID#\",\"#=TPName#\")' title='#=TPName#'><div class='DisplayTitleTPName'>#=TPName#<ul><li>AM: #=AM#, OM: #=OperatingModel#, Country: #=Country#</li><li>DevSales Lead: #=SalesLead#, SSP: #=Dev_SSP#, TSP: #=DevTSP#</li></ul></div></a>", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{
"title": "PERFORMANCE AND ANNIVERSARIES", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns:
[{
"title": "Renewals and True Ups", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns: [{ "title": "Total Annualized Expiring", "field": "EndCustomerPurchaseAmt", format: "{0:c0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Primary Anniversary Month", "field": "PrimaryExpirationMonth", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Agreement Number", "field": "AgreementID", format: "{0:n0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } }]
}]
},
{
"title": "EFFECTIVE LICENSE POSITIONS", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns:
[{
"title": "Visual Studio Subscriptions", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns: [{ "title": "Purchased", "field": "TotalPurchased", format: "{0:n0}" },
{ "title": "Assigned", "field": "TotalAssigned", format: "{0:n0}" },
{ "title": "Over Under", "field": "OverUnder", format: "{0:n0}" }]
},
{
"title": "Account Footprint (Active SA Licenses)", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns: [{ "title": "Enterprise w/ MSDN", "field": "VSEntPurchasedUnits", format: "{0:n0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Pro w/ MSDN", "field": "VSProMSDNUnits", format: "{0:n0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Test Pro w/ MSDN", "field": "VSTestProMSDNUnits", format: "{0:n0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "MSDN Platforms", "field": "MSDNPlat", format: "{0:n0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Cloud", "field": "CloudPurchasedUnits", format: "{0:n0}" }]
},
{
"title": "Azure", headerAttributes: { style: "text-align: center;font-weight: bold;" },
columns: [{ "title": "Unbilled Overage", "field": "UnbilledOverage", format: "{0:c0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } },
{ "title": "Potential Revenue", "field": "AzurePotentialRevenue", headerTemplate: '<span title="Potential Revue is based on the delta of activated seats and <br/> developers deploying to Azure multiplied by the annual <br/> value of an Azure attached developer ($15k)">Potential Revenue</span>', format: "{0:c0}", headerAttributes: { style: "white-space: normal; overflow: visible;" } }]
}]
}
],
groupable: false,
sortable: true,
resizable: true,
//pageable: true,
pageable: {
refresh: true,
pageSizes: [10, 20, 50],
},
columnMenu: true,
scrollable: false
//filterable: true
};
$("#heatMapGrid").data("kendoGrid").setDataSource(dataSourceHeatMapGrid);
AngularJS服务:
services.getHeatMapGrid = function (command, heatMapGridParams) {
var data = {
page: command.page,
pageSize: command.pageSize,
skip: command.skip,
take: command.take,
alias: heatMapGridParams.alias,
hasDevTest: heatMapGridParams.hasDevTest,
hasDevTestLabs: heatMapGridParams.hasDevTestLabs,
hasXamarin: heatMapGridParams.hasXamarin,
devOpsMSShopFlag: heatMapGridParams.devOpsMSShopFlag,
devOpsOSSThirdPartyShopsFlag: heatMapGridParams.devOpsOSSThirdPartyShopsFlag,
intelligentAppsFlag: heatMapGridParams.intelligentAppsFlag,
paaSServicesFlag: heatMapGridParams.paaSServicesFlag,
enterpriseStepUpFlag: heatMapGridParams.enterpriseStepUpFlag,
devsLearningAzureFlag: heatMapGridParams.devsLearningAzureFlag,
devOpsAcceleratorEligibleFlag: heatMapGridParams.devOpsAcceleratorEligibleFlag,
overAssignedFlag: heatMapGridParams.overAssignedFlag,
lowAssignmentsFlag: heatMapGridParams.lowAssignmentsFlag,
hasCloudSubscriptionFlag: heatMapGridParams.hasCloudSubscriptionFlag,
hasUnbilledOverageFlag: heatMapGridParams.hasUnbilledOverageFlag,
hasDevTestOppty: heatMapGridParams.hasDevTestOppty,
areaID: heatMapGridParams.areaID,
countryID: heatMapGridParams.countryID,
segmentID: heatMapGridParams.segmentID,
subsegmentID: heatMapGridParams.subsegmentID,
salesUnitID: heatMapGridParams.salesUnitID,
agreementRenewalOrTrueupID: heatMapGridParams.agreementRenewalOrTrueupID,
aM: heatMapGridParams.aM,
industry: heatMapGridParams.industry,
hasAppServOppty: heatMapGridParams.hasAppServOppty,
hasDotNetDeveloperFlag: heatMapGridParams.hasDotNetDeveloperFlag,
paaSReadyFlag: heatMapGridParams.paaSReadyFlag,
startMonth: heatMapGridParams.startMonth,
endMonth: heatMapGridParams.endMonth
};
return $http({ method: 'GET', url: config.apiUrl + 'Account/HeatMapGrid/', params: data });
};
Web API:
[HttpGet]
public heatMapGridAndExport HeatMapGrid([FromUri]HeatMapGridModel model)
{
ListView listView = new ListView();
List<getHeatMapDataGlobalFilter_Result> listGridDataForTotalCount = new List<getHeatMapDataGlobalFilter_Result>();
listGridDataForTotalCount = listView.GetListViewGridData(model.alias, model.hasDevTest, model.hasDevTestLabs, model.hasXamarin, model.devOpsMSShopFlag, model.devOpsOSSThirdPartyShopsFlag, model.intelligentAppsFlag, model.paaSServicesFlag, model.enterpriseStepUpFlag, model.devsLearningAzureFlag, model.devOpsAcceleratorEligibleFlag, model.overAssignedFlag, model.lowAssignmentsFlag, model.hasCloudSubscriptionFlag, model.hasUnbilledOverageFlag, model.hasDevTestOppty, model.areaID, model.countryID, model.segmentID, model.subsegmentID, model.salesUnitID, model.agreementRenewalOrTrueupID, model.aM, model.industry, model.hasAppServOppty, model.hasDotNetDeveloperFlag, model.paaSReadyFlag, model.startMonth, model.endMonth);
List<getHeatMapDataGlobalFilter_Result> listGridData = new List<getHeatMapDataGlobalFilter_Result>();
listGridData = listGridDataForTotalCount.Skip(model.skip).Take(model.take).OrderByDescending(c => c.EndCustomerPurchaseAmt).ToList();
//List<heatMapExport> listExportData = new List<heatMapExport>();
//listExportData = listGridDataForTotalCount.Select(c => new heatMapExport()
//{
// TPName = c.TPName,
// TPID = c.TPID,
// OperatingModel = c.OperatingModel,
// Area = c.Area,
// Country = c.Country,
// CreditedRegion = c.CreditedRegion,
// CreditedDistrict = c.CreditedDistrict,
// Segment = c.Segment,
// ATUManager = c.ATUManager,
// Dev_SSP = c.Dev_SSP,
// AM = c.AM,
// Industry = c.Industry,
// ATSName = c.ATSName,
// AssignedPect = string.Format("{0:p0}", c.AssignedPect),
// ActivatedPect = string.Format("{0:p0}", c.ActivatedPect),
// AzureActivated = Convert.ToString(c.AzureActivated),
// EndCustomerPurchaseAmt = string.Format("{0:c0}", c.EndCustomerPurchaseAmt),
// PrimaryExpirationMonth = Convert.ToString(c.PrimaryExpirationMonth),
// AgreementID = Convert.ToString(c.AgreementID),
// TotalPurchased = string.Format("{0:n0}", c.TotalPurchased),
// TotalAssigned = string.Format("{0:n0}", c.TotalAssigned),
// OverUnder = string.Format("{0:n0}", c.OverUnder),
// VSEntPurchasedUnits = string.Format("{0:n0}", c.VSEntPurchasedUnits),
// VSProMSDNUnits = string.Format("{0:n0}", c.VSProMSDNUnits),
// VSTestProMSDNUnits = string.Format("{0:n0}", c.VSTestProMSDNUnits),
// MSDNPlat = string.Format("{0:n0}", c.MSDNPlat),
// CloudPurchasedUnits = string.Format("{0:n0}", c.CloudPurchasedUnits),
// UnbilledOverage = string.Format("{0:c0}", c.UnbilledOverage),
// AzurePotentialRevenue = string.Format("{0:c0}", c.AzurePotentialRevenue)
//}).ToList();
var heatMapData = new heatMapGridAndExport
{
gridData = listGridData,
//exportData = listExportData,
Total = listGridDataForTotalCount.Count()
};
return heatMapData;
}
我的环境:
版本Telerik Control - Kendo UI v2017.2.621
操作系统开发机器 - Windows 10 Enterprise(8 GB RAM,Intel Core i7处理器,64位)(客户端操作系统)
浏览器 - 谷歌浏览器,版本65.0.3325.181
.NET Framework - 版本4.6.1
Visual Studio - Enterprise 2015,版本14.0.25431.01(更新3)
编码语言 - C#
以下是我为生产服务器拍摄的浏览器屏幕:
这是另一个截图,当我点击第二页时,它再次下载38 MB的内容,大约需要。 6分钟。 (server paging = true和pageSize = 10)
代码调试截图:
我做错了什么?任何人都可以帮助我。
提前谢谢。
答案 0 :(得分:1)
您是否可以禁用将~56K行导出数据附加到WebAPI响应的行并查看其执行情况?我怀疑那是你的问题
var heatMapData = new heatMapGridAndExport
{
gridData = listGridData,
//exportData = listExportData, //perhaps make conditional, for export only?
Total = listGridDataForTotalCount.Count()
};
return heatMapData;
编辑:由于这似乎没有解决你的问题,你可以尝试重新排序这样的Linq方法调用,因为你得到的行为暗示整个结果集回来了吗?
listGridData =
listGridDataForTotalCount.OrderByDescending(c => c.EndCustomerPurchaseAmt)
.Skip(model.skip).Take(model.take).ToList();
我不确定,但我想知道OrderByDescending
最后是否迫使Linq回到整个结果集,这是你最终从ToList
得到的?