将大型数据集加载到c#GridView中时出现性能问题
本文关键字:性能 问题 c#GridView 大型 数据集 加载 | 更新日期: 2023-09-27 18:25:38
好的,
一直在我的GridView中测试相对较小的数据集,一切都很好。然而,我现在已经进入了适当的UAT,并试图将17000条记录加载到我的网格中,这基本上使我的网络应用程序陷入了停顿。
基本上,用户登录,验证后加载所有数据网格,其中一个包含17k条记录。在加载完所有内容之前,最终用户将一直处于登录页面上。所以我需要修复它。
网格的代码是:
DataTable dtValueDateCurrency = null;
SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["Reporting"].ConnectionString);
using (conn)
{
conn.Open();
//Load all other grid data
using (SqlDataAdapter sqlAdapter = new SqlDataAdapter(TSQL1, conn))
{
dtValueDateSummary = new DataTable();
sqlAdapter.Fill(dtValueDateSummary);
grdValueDateSummary.DataSource = dtValueDateSummary;
grdValueDateSummary.DataBind();
}
}
有没有办法增加加载时间?分页不是一个选项,因为我正在用JQuery处理这个问题。
在一个查询中加载17000条记录会让你丧命。我强烈建议浏览你的网格视图。
首先,您需要按如下方式更改存储过程。
ALTER PROCEDURE [dbo].[SomeTable_GetPagedResults]
(
@StartRowIndex int,
@MaximumRows int
)
AS
SET NOCOUNT ON
Select
RowNum,
[ID],
[foo],
[bar]
From
(Select
[ID],
[foo],
[bar],
Row_Number() Over(Order By [ID] Desc) As RowNum
From dbo.[SomeTable] t)
As DerivedTableName
Where RowNum Between @StartRowIndex And (@StartRowIndex + @MaximumRows)
现在您有了一个可分页的查询。
您还需要一个查询来获取完整的行计数。
ALTER PROCEDURE [dbo].[SomeTable_GetRowCount]
AS
SET NOCOUNT ON
return (Select Count(ID) As TotalRecords From SomeTable)
每次更改页面时,都会绑定网格。
protected void gridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
gridView1.PageIndex = e.NewPageIndex;
BindGrid(); // this is whatever method you call to bind your data and execute your stored procedure.
}
BindGrid()
方法将调用您的两个存储过程(一个用于获取完整的行计数,另一个用于获得与当前页面相关的结果)
附加读取
您需要建立数据库分页。
这将涉及创建自定义排序、自定义筛选和自定义分页,但它将显著提高代码的性能,因为您一次只能从数据库中检索相当于一页的数据,而不是一次检索全部17000行。
我在一个银行应用程序中实现了这一点,该应用程序旨在显示、排序和过滤数十万笔贷款。答案太复杂了,无法给出一个简单的例子,而是从研究数据库分页开始。使用LINQ,它将为您提供简单的Take
和Skip
方法,以实现最简单的分页。
您应该考虑在web服务器上缓存查询,尤其是在它很少更新的情况下。这样,所有客户端都可以简单地从缓存中浏览,而不是无情地访问数据库。
请参阅此SO问题
实际上,一次加载17k记录是没有用的,即使用户不能一次看到整个17k记录。我建议您将分页与DataTable.Merge
函数一起使用,该函数有助于以块的形式加载记录,并将新获取的数据附加到前一个数据中。我只是做了一个快速测试,找到了解决方案。试试看。
没有解决方案分页很慢,会一次又一次地调用数据库,所以你需要放入
<style>.body{display:none;}</style>
页面的开头并且在页面的末尾
<style>.body{display:block;}</style>