65.9K
CodeProject 正在变化。 阅读更多。
Home

在 GridView 中显示大量数据并实现搜索功能

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.79/5 (24投票s)

2010年9月2日

CPOL

7分钟阅读

viewsIcon

211299

downloadIcon

16264

本文介绍了如何在 ASP.NET 3.5 中的 GridView 中显示大量数据并实现搜索功能。

第一部分

GridView1.jpg

引言

本文介绍了如何在 ASP.NET 3.5 中的 GridView 中显示数千甚至数百万条数据。

在第一部分,我们的主要目标是在 gridview 显示大量数据时实现超快的性能。当用户导航数据时,他们不应该感觉自己在导航数百万条数据。

在第二部分,我们将实现 GridView 上的搜索功能。

为了实现这一目标,我们将利用自定义分页、缓存和 AJAX。我们还将在这一部分实现排序。我使用了 SQL Server 2008 的 AdventureWorks 示例数据库。

背景

需要具备 ASP.NET 3.5、C#、自定义分页、GridView、缓存、AJAX、SQL Server 2008 和 VS 2008 的基础知识。

除此外,我还使用了 DataPagerGridView 进行自定义分页。最初,您不能直接将 DataPagerGridView 一起使用,因为 DataPager 可与实现 IPageableItemContainer 接口的控件一起使用。因此,我们需要创建一个派生自 GridView 并实现 IPageableItemContainer 的新自定义控件。

有关更多信息,请访问 此处

概述

让我们先来理解整个流程。当 GridView 首次显示时,我们将检查数据是否已缓存。如果未缓存,我们将从数据库中获取所有记录并存储在缓存中。

我们将根据页索引和每页记录数显示有限数量的记录。我们将按如下方式计算自定义分页的 StartingRowIndexMaximumRecords

StartingRowIndex = (PageIndex -1)*PageSize; 
MaximumRecords = PageSize. 

如果页索引是 1,每页记录数是 10,则 startingRowIndex 将是 0MaximumRecords 将是 10,因此我们将从 0 到 9 返回 datatable 中的 10 行。同样,如果页索引是 2,每页记录数是 10,则 startingRowIndex 将是 10MaximumRecords 将是 10,因此我们将从 datatable 中从第 10 行到第 19 行返回 10 行。

所以,每次我们只绑定 10 条记录到 GridView,但我们将根据数据库中的总记录数显示页码。这就是自定义分页和 DataPager 发挥作用的地方。

Using the Code

该项目中有两个独立的层:

  1. UI
  2. 数据访问层

我在同一项目的一个不同文件夹中创建了 DAL,但如果您愿意,可以为 DAL 创建一个单独的项目。即使您想将其制作成三层应用程序,也可以为 UI 和 DAL 链接的业务层创建一个单独的项目。但为了简单起见,我在同一个项目中创建了 DAL。

那么,让我们一步一步地开始我们的旅程。

步骤 1:首先在 VS 2008 中创建一个 Web 应用程序项目。保留所有设置不变。我们将使用 GridViewDataPager。因此,我们需要创建一个派生自 GridView 类并实现 IPageableItemContainer 的服务器控件。请访问 此处 以更好地理解,因为本文不是关于将 datapagerGridView 一起使用。

步骤 2:创建 GridView 服务器控件后,让我们创建数据访问层。我在 SQL Server 2008 中使用了 AdvantureWorks 示例数据库。因此,您可以下载此示例数据库来运行示例代码。

为数据访问层添加一个新文件夹“DAL”。添加一个名为“AdvWorksDB”的新类。我们将从 AdvantureWorks 数据库中的 DimCustomer 表获取客户数据。此表有超过 18000 条记录。

AdvWorksDB 类将有两个函数:

  • GetCustomerSortedPage
  • GetCustomersCount

请记住一件事,我们处理的是大量数据。因此,为了提高性能,我们不能一次性获取所有记录并将其绑定到 gridview。如果这样做,您的页面将崩溃。因此,我们将获取 gridview 特定页面的数据,例如 10、25、50 条记录。因此,在任何时候,我们都只获取有限的记录并将其绑定到 grid,假设每页记录数为 pagesize 时为 10 条记录。

private const string CUSTOMER_CACHE_KEY = "CUSTOMER_DATA";
private const string CUSTOMERCOUNT_CACHE_KEY = "CUSTOMER_COUNT";

        public static DataTable GetCustomersSortedPage
	(int maximumRows, int startRowIndex, 
		string sortExpression, string searchCriteria)
        {
            if (string.IsNullOrEmpty(sortExpression))
                sortExpression = "customerkey";
            try
            {
                if (AdvWorksDBCache.isRecordsCached(CUSTOMER_CACHE_KEY))
                    return AdvWorksDBCache.GetData
			(CUSTOMER_CACHE_KEY, startRowIndex + 1, 
			maximumRows, sortExpression, searchCriteria);

                SqlConnection dbConnection = new SqlConnection
		(ConfigurationManager.ConnectionStrings["SQLDBConString"].ToString());
                string sql = "select Cust.*,G.City from 
		DimCustomer Cust inner join DimGeography G on 
		G.GeographyKey = Cust.GeographyKey ";
                SqlCommand custCommand = new SqlCommand(sql, dbConnection);

                custCommand.CommandType = CommandType.Text;

                SqlDataAdapter ad = new SqlDataAdapter(custCommand);
                DataTable dtCustomers = new DataTable();
                ad.Fill(dtCustomers);
                dbConnection.Close();

                //Cache records
                AdvWorksDBCache.Add(CUSTOMER_CACHE_KEY,dtCustomers);
            }
            catch (Exception e)
            {
                throw;
            }
            return AdvWorksDBCache.GetData(CUSTOMER_CACHE_KEY, startRowIndex + 1, 
		maximumRows, sortExpression, null);
        }
        

在此函数中,我们首先检查数据是否已缓存?如果数据未缓存,我们将获取所有记录并将其添加到缓存中,然后从缓存中返回一部分记录。AdvWorksDBCache 是一个用于缓存的类。我们很快就会看到它。

第二个函数是 GetCustomersCount,它返回 DimCustomer 表中的记录数。

public static int GetCustomersCount(string searchCriteria)
        {
            int custCount = 0;
            try
            {
                SqlConnection dbConnection = new SqlConnection
		(ConfigurationManager.ConnectionStrings["SQLDBConString"].ToString());
                string sql = "select count(*) from DimCustomer ";

                if (!string.IsNullOrEmpty(searchCriteria))
                    sql = sql + " where " + searchCriteria;
                
                SqlCommand sqlCommand = new SqlCommand(sql, dbConnection);
                sqlCommand.Connection = dbConnection;
                dbConnection.Open();
                sqlCommand.CommandType = CommandType.Text;

                custCount = Convert.ToInt32(sqlCommand.ExecuteScalar());

                dbConnection.Close();

                if (AdvWorksDBCache.Get(CUSTOMERCOUNT_CACHE_KEY) != null)
                {
                    // remove customers data if customers count has changed 
                    // since first cache
                    if (Convert.ToInt32(AdvWorksDBCache.Get(CUSTOMERCOUNT_CACHE_KEY)) != 
			custCount && string.IsNullOrEmpty(searchCriteria))
                    {
                        AdvWorksDBCache.Remove(CUSTOMER_CACHE_KEY);
                    }
                }

                if (string.IsNullOrEmpty(searchCriteria))
                    AdvWorksDBCache.Add(CUSTOMERCOUNT_CACHE_KEY , custCount);
            }
            catch (Exception e)
            {
                throw;
            }
            return custCount ;
        }

我们在这里使用缓存只是为了减少不必要的数据库调用。因此,添加一个名为“AdvWorksDBCache”的新类。该类将具有标准的函数,如 AddGetRemove 用于缓存。它还有一个 GetData 函数,仅用于从缓存数据中返回数据页。请参阅源代码以获得更好的理解。

步骤 3:现在我们将创建 UI。您可以在工具栏中找到 GridView 服务器控件。将其拖放到 default.aspx。暂时将其保持原样。稍后我们将对其进行配置。

现在从工具栏将 ObjectDataSource 拖放到 Default.aspx。我们必须为 ObjectDataSource 设置以下属性:

  1. Id = odsCustomers
  2. SelectMethod = GetCustomersSortedPage
  3. SelectCountMethod = GetCustomersCount
  4. TypeName = DemoGrid.DAL.AdvWorksDB (完整的 DB 类名)
  5. SortParameterName = sortExpression
  6. EnablePaging = true

GridView2.jpg

设置完这些属性后,您的代码将如下所示:

<asp:ObjectDataSource ID="odsCustomers" runat="server" 
                    SelectMethod="GetCustomersSortedPage" 
			TypeName="DemoGrid.DAL.AdvWorksDB" 
                    EnablePaging="True" SelectCountMethod="GetCustomersCount" 
                    SortParameterName="sortExpression">
</asp:ObjectDataSource>

现在将 DataPager 拖放到 Default.aspx 并根据您的分页格式设置属性。我已将其设置如下:

<asp:DataPager  ID="pager" runat="server" PagedControlID="gvCustomers">       
	<Fields>                                            
       		<asp:NextPreviousPagerField FirstPageText="<<" LastPageText=">>" 
                                NextPageText=">"  PreviousPageText="<" 
					ShowFirstPageButton="True"
                                ShowNextPageButton="False" ButtonCssClass="datapager" />
                  <asp:NumericPagerField ButtonCount="10"  
			NumericButtonCssClass="datapager" 
			CurrentPageLabelCssClass="datapager"   />
                  <asp:NextPreviousPagerField LastPageText=">>" NextPageText=">" 
                                ShowLastPageButton="True" 
			ShowPreviousPageButton="False" ButtonCssClass="datapager" />
        </Fields>
</asp:DataPager>

现在是时候配置 gridview 了。我们必须将 DataSourceId 设置为 odsCustomers,这是我们的 ObjectDataSourceAutoGenerateColumns = falseAllowSorting = true,并设置 OnDataBound 事件。在这里,我们还需要 pagesize 下拉框和 GridView 底部的 label,以便用户可以更改每页记录数。我已将其配置如下:

<cc1:GridView  ID="gvCustomers" runat="server" AutoGenerateColumns="False" 
		AllowSorting="True"
                  CssClass="tablestyle" OnDataBound="gvCustomers_DataBound" 
			DataSourceID="odsCustomers" AllowPaging="True" >        
                     <AlternatingRowStyle CssClass="altrowstyle" />
                    <HeaderStyle CssClass="headerstyle" />
                    <RowStyle CssClass="rowstyle" Wrap="false" />  
                    <EmptyDataRowStyle BackColor="#edf5ff" Height="300px" 
			VerticalAlign="Middle" HorizontalAlign="Center" />
                    <EmptyDataTemplate >
                        No Records Found
                    </EmptyDataTemplate>
                    <Columns>
                        <asp:BoundField SortExpression="customerkey" 
			DataField="customerkey" HeaderText="Customer Key" />
                        <asp:BoundField SortExpression="City" 
			DataField="City" HeaderText="City" />
                        <asp:BoundField DataField="CustomerAlternateKey" 
			HeaderText="Customer Alternate Key" 
			SortExpression="CustomerAlternateKey" />
                        <asp:BoundField DataField="Title" HeaderText="Title" 
				SortExpression="Title"/>
                        <asp:BoundField DataField="FirstName" 
			HeaderText="First Name" SortExpression="FirstName"/>
                        <asp:BoundField DataField="LastName" 
			HeaderText="Last Name" SortExpression="LastName"/>
                        <asp:BoundField DataField="BirthDate" 
			HeaderText="Birth Date" SortExpression="BirthDate"/>
                    </Columns>
                    <PagerTemplate >
                         <table width="100%" >
                            <tr>
                                <td style="text-align:  left">
                                    Page Size: 
                                    <asp:DropDownList ID="ddPageSize" 
				runat="server" EnableViewState="true" 
				OnSelectedIndexChanged=
				"ddPageSize_SelectedIndexChanged" 
				AutoPostBack="true">
                                        <asp:ListItem Text="10" ></asp:ListItem>
                                        <asp:ListItem Text="25" ></asp:ListItem>
                                        <asp:ListItem Text="50" ></asp:ListItem>
                                    </asp:DropDownList>
                                </td>
                                <td style="text-align: right">
                                    <asp:Label ID="lblPageCount" runat="server">
				</asp:Label>
                                </td>
                            </tr>
                        </table>
                    </PagerTemplate>
</cc1:GridView>  

现在您可以运行了。看看它的性能。您可以将 datapagergridview 放在 AJAX updatepanel 中,以消除闪烁效果。

在第二部分,我们将添加 GridView 的搜索功能。

注释

  • 我编写了一个缓存类,只是为了演示缓存能力。您可以根据需要修改缓存类并添加依赖项。您可以利用 ObjectDataSource 的缓存属性。
  • 您可以像平常使用 GridView 一样插入 checkbox 列。但在这里,当用户选中/取消选中 checkbox 并导航到数据时,您必须维护一个已选行列表。
  • 您也可以使用 LINQ to SQL。您只需修改生成类中的方法即可在 ObjectDataSource 中使用。

第二部分

我们讨论了如何在不影响性能的情况下在 GridView 中显示大量数据。现在在第二部分,我们将继续使用同一个示例,并在 GridView 上构建搜索功能。

GridviewSearch2.jpg

概述

我们将搜索缓存的数据,并将仅 10 条记录(取决于每页记录数)绑定到 GridView。这样,我们可以减少数据库调用并保持性能。

Using the Code

首先,我们必须在 GridView 上方添加搜索标题。我们将添加一个用于列的 dropdownbox,一个用于搜索条件的另一个 dropdown,以及一个用于搜索值的 textbox。我们还将添加“搜索”和“重置”按钮。我已将此代码添加在 GridView 上方的面板中,如下所示:

<asp:Panel ID="pnlSearch" runat="server" >
            <table style="background-color:#C7CFF7; border-width:3px; 
		border-style:solid; margin: 0px 20px 0px 0px;">
                <tr>
                    <td colspan="5">
                        <asp:Label ID="lblSearchError" runat="server" 
			ForeColor="Red" ></asp:Label>
                    </td>
                </tr>
                <tr>
                    <td align="left">Search Column</td>
                    <td align="left">Search Criteria</td>
                    <td align="left">Search Value</td>
                    <td></td>
                    <td></td>
                </tr>
                
                <tr>
                    <td><asp:HiddenField ID="hfSearchCriteria" runat="server" />
                        <asp:DropDownList ID="ddSearchField" Width="150px" runat="server">
                            <asp:ListItem Text="Customer Key" 
				Value="customerkey"></asp:ListItem>
                            <asp:ListItem Text="City" Value="City"></asp:ListItem>
                            <asp:ListItem Text="Customer Alternate Key" 
				Value="CustomerAlternateKey"></asp:ListItem>
                            <asp:ListItem Text="Title" Value="Title"></asp:ListItem>
                            <asp:ListItem Text="First Name" Value="FirstName">
			</asp:ListItem>
                            <asp:ListItem Text="Last Name" Value="LastName">
			</asp:ListItem>
                            <asp:ListItem Text="Birth Date" Value="BirthDate">
			</asp:ListItem>
                        </asp:DropDownList>
                    </td>
                    <td>
                        <asp:DropDownList ID="ddSearchCriteria" runat="server">
                            <asp:ListItem Text= "Contains" ></asp:ListItem>
                            <asp:ListItem Text= "DoesNotContain" ></asp:ListItem>
                            <asp:ListItem Text="EqualTo" ></asp:ListItem>
                            <asp:ListItem Text= "NotEqualTo" ></asp:ListItem>
                            <asp:ListItem Text= "GreaterThan"></asp:ListItem>
                            <asp:ListItem Text= "LessThan" ></asp:ListItem>
                            <asp:ListItem Text= "GreaterThanOrEqualTo" ></asp:ListItem>
                            <asp:ListItem Text= "LessThanOrEqualTo"></asp:ListItem>
                        </asp:DropDownList>
                    </td>
                    <td>
                        <asp:TextBox ID="txtSearchValue" runat="server"></asp:TextBox> 
                    </td>
                    <td>
                        <asp:Button ID="btnSearch" CssClass="searchbtn" 
			runat="server"  OnClick="btnSearch_Click" Text="Search" />
                    </td>
                    <td>
                        <asp:Button ID="btnReload" CssClass="reloadbtn" 
			runat="server"  OnClick="btnReload_Click" Text="Reload" />
                    </td>
                </tr>
                </table>
</asp:Panel>

如果您注意到,我使用了 1 个隐藏字段“hfSearchCriteria”,它将包含完整的搜索条件字符串,例如“CustomerKey=11000”。我们将将其作为 SelectParameters 传递给 ObjectDataSourse,如下所示:

<asp:ObjectDataSource ID="odsCustomers" runat="server" 
                SelectMethod="GetCustomersSortedPage" TypeName="DemoGrid.DAL.AdvWorksDB" 
                EnablePaging="True" SelectCountMethod="GetCustomersCount" 
                SortParameterName="sortExpression">
                <SelectParameters>
                    <asp:ControlParameter  ControlID="hfSearchCriteria" 
			Name="searchCriteria" Direction="Input"  />
                </SelectParameters>                                            
 </asp:ObjectDataSource>

您可以通过向 ObjectDataSource 的属性窗口添加 SelectParameters 集合来设置此项,如下所示:

GridviewSearch1.jpg

每当绑定 GridView 时,ObjectDataSource 都会将隐藏字段的值传递给 select 方法。在我们的例子中,它是“GetCustomerSortedPage”。实际的搜索发生在缓存类 AdvWorksDBCache 中。如果您查看 AdvWorksDBCacheGetData 方法,我们会根据搜索条件过滤 datatable,并根据 startingRowIndexMaximumRecords 返回记录。在搜索按钮单击时,我们只需构建搜索字符串并将其分配给隐藏字段,然后重新绑定 GridView。请参阅附加的源代码以获得更多理解。这样,我们就可以在 GridView 上实现搜索功能。希望您会喜欢。

© . All rights reserved.