【编者按】本文作者为来自巴基斯坦的软件开发工程师 Aqeeel,主要介绍了在 SQL 查询层面实现 ASP.NET 应用的分页方法。

本文系 OneAPM 工程师编译呈现,以下为正文。

GridView 提供了一种实现分页的方法。但是,随着记录的不断扩大,我们需要在查询层面进行优化。

简介

在 SQL 查询层面实现 ASP.NET 程序分页,而不借助 GridView。

背景

无可否认,GridView 是在 ASP.NET Web 表单展示数据的强大工具,它能在结果集较大时实现分页。然而,后端会获取完整的数据,抽取出相关数据,然后通过 GridView 展示在 Web 表单中。在这种情况下,相关数据只是完全抽取数据的一小部分。这些多余的数据造成了处理能力、内存空间以及时间的极大浪费。在本文中,我们将展示如何仅从数据库抽取所需数据,从而避免这些浪费。

下图展示了从数据库中获取完整数据的方式。在渲染阶段,相关数据会被抽取出来,填充到 GridView 中。

下图展示了从数据库中抽取过滤或相关数据的方式,进而得到更小的数据集。在 Web 应用中,同样的数据集无需经过进一步抽取,就可以填充到 GridView 中。

具体实现

工具

本例借助 SQL Server 2014 与 Visual Studio 2015 实现。2012 之前的 SQL Server 版本不支持 FETCH,但是使用 ROW NUMBER 可以达到同样的效果。

首先进行后端设置:

  1. 创建名为 TestPagingInASPNET 的数据库,

  2. 创建名为 AdministrativeUnits 与 Cities 的两张表。

  3. 创建存储过程(Stored Procedures,简称 SP),用于从数据库获取数据。请注意,笔者创建了两个存储过程,名字分别为 SelectCitiesWithPaging 与 SelectCitiesWithPagingOldSQLVersions。由于笔者是在 SQL Server 2014 中实现该解决方案的,在第一个 SP 中,笔者使用了 OFFSET FETCH 声明。对于更早的版本,比如 SQL Server 2005 与 SQL Server 2008,则应该使用 ROW_NUMBER() 函数而非 OFFSET FETCH。因此,请创建与开发环境相适合的 SP。与传统的 SP 不同,此处创建的 SP 将包含三个参数,细节如下:

@PageNumber 为将会返回的页码数(Page Number)
@RowsPerPage 为每页的行数(Number of Rows)
@TotalResords(输出参数)为总的记录

-- CREATE DATABASE
CREATE DATABASE TestPagingInASPNET;
GO-- CREATE FIRST TABLE
CREATE TABLE AdministrativeUnits (AdministrativeUnitID INT PRIMARY KEY IDENTITY(1, 1),Name VARCHAR(50)
);
GO-- CREATE SECOND TABLE
CREATE TABLE Cities (CityID INT PRIMARY KEY IDENTITY(1, 1),AdministrativeUnitID INT,Name VARCHAR(50)
);
GO-- CREATE THE STORED PROCEDURE
CREATE PROCEDURE SelectCitiesWithPaging@PageNumber INT,@RowsPerPage INT,@TotalRows INT OUTPUT
AS
BEGINSET NOCOUNT ON;SELECT        @TotalRows = COUNT(*)FROM        [AdministrativeUnits] [AU]INNER JOIN    [Cities] [C] ON [AU].[AdministrativeUnitID] = [C].[AdministrativeUnitID]SELECT        [AU].[Name] [Administrative Unit],[C].[Name] [City]FROM        [AdministrativeUnits] [AU]INNER JOIN    [Cities] [C] ON [AU].[AdministrativeUnitID] = [C].[AdministrativeUnitID]ORDER BY    [AU].[Name], [C].[Name]OFFSET        ((@PageNumber - 1) * @RowsPerPage) ROWS FETCH NEXT @RowsPerPage ROWS ONLYEND
GO-- CREATE THE STORED PROCEDURE
CREATE PROCEDURE SelectCitiesWithPagingOldSQLVersions@PageNumber INT,@RowsPerPage INT,@TotalRows INT OUTPUT
AS
BEGINSET NOCOUNT ON;SELECT        @TotalRows = COUNT(*)FROM         [AdministrativeUnits] [AU]INNER JOIN    [Cities] [C] ON [AU].[AdministrativeUnitID] = [C].[AdministrativeUnitID]SELECT    *FROM    (    SELECT        ROW_NUMBER() OVER (ORDER BY [AU].[Name], [C].[Name]) NUMBER,[AU].[Name] [Administrative Unit],[C].[Name] [City]FROM        [AdministrativeUnits] [AU]INNER JOIN    [Cities] [C] ON [AU].[AdministrativeUnitID] = [C].[AdministrativeUnitID]) tblWHERE    Number BETWEEN ((@PageNumber - 1) * @RowsPerPage + 1) AND (@PageNumber * @RowsPerPage)
END
GO

现在,讨论应用的前端部分

ASPX

  • 在 Web 表单中绘制一个表格,其包含两个表格行(Table Rows)

  • 在第一个表格行中推拽下放一个 GridView。此处无需启用分页,因为存储过程实现该功能。

  • 在第二个表格行中,放置两个按钮来实现前页与后页之间的跳转。此外,为两个按钮创建点击事件。

  • 在第三个表格行中,放置页面导航链接。

  • 在下面;提供了 .aspx 文件中的代码。

    <table style="width:100%;"><tr><td><asp:GridView ID="GridView1" runat="server"></asp:GridView></td></tr><tr><td style="text-align:center;"><asp:Button ID="btnGridViewPrevious" runat="server" OnClick="btnGridViewPrevious_Click" Text="&lt;" /><asp:TextBox ID="txtGridViewPageNumber" runat="server"></asp:TextBox><asp:Button ID="btnGridViewGoToPageNumber" runat="server" Text="Go to Page" OnClick="btnGridViewGoToPageNumber_Click" /><asp:Button ID="btnGridViewNext" runat="server" OnClick="btnGridViewNext_Click" Text="&gt;" /></td></tr><tr><td style="text-align:center;" runat="server" id="tdPage"></td></tr></table>

ASPX.cs

在 .aspx.cs 文件中,我们会创建两个函数。

GetAndBindData()

  1. 第一个函数将得到来自数据库的请求数据。请注意,我们以页码数与每页的行数为参数。

  2. 接收到的数据将填充在网格中。

  3. 在页面加载(Page Load)事件触发,且参数页面数(PageNumber)为1时,即会调用该函数。

CreatePager()

  1. 第二个函数将创建用于导航的链接。

private void GetAndBindData(Int32 PageNumber, Int32 RowsPerPage)
{SqlConnection con = new SqlConnection(ConnectionString);SqlCommand cmd = new SqlCommand();cmd.CommandType = System.Data.CommandType.StoredProcedure;cmd.CommandText = "SelectProjects";cmd.Connection = con;SqlParameter par1 = new SqlParameter();par1.ParameterName = "PageNumber";par1.DbType = System.Data.DbType.Int32;par1.Direction = System.Data.ParameterDirection.Input;par1.Value = PageNumber;cmd.Parameters.Add(par1);SqlParameter par2 = new SqlParameter();par2.ParameterName = "RowsPerPage";par2.DbType = System.Data.DbType.Int32;par2.Direction = System.Data.ParameterDirection.Input;par2.Value = RowsPerPage;cmd.Parameters.Add(par2);SqlParameter par3 = new SqlParameter();par3.ParameterName = "TotalRows";par3.DbType = System.Data.DbType.Int32;par3.Direction = System.Data.ParameterDirection.Output;cmd.Parameters.Add(par3);SqlDataAdapter adp = new SqlDataAdapter();adp.SelectCommand = cmd;DataSet ds = new DataSet();con.Open();adp.Fill(ds);Session["TotalRows"] = par3.Value.ToString();GridView1.DataSource = ds.Tables[0];GridView1.DataBind();
}private void CreatePager(Int32 TotalRecords, Int32 PageNumber, Int32 RowsPerPage)
{Int32 intIndex;Int32 intPageNumber;tdPage.InnerHtml = "";intPageNumber = 1;for (intIndex = 1; intIndex <= TotalRecords; intIndex+=10){tdPage.InnerHtml += " <a href=''>" + intPageNumber.ToString() + "</a> ";intPageNumber++;}if (TotalRecords > intIndex) {tdPage.InnerHtml += " <a href=''>" + intIndex.ToString() + "</a> ";}
}protected void btnGridViewNext_Click(object sender, EventArgs e)
{Int32 NewPageNumber = Convert.ToInt32(Session["PageNumber"]);NewPageNumber++;Session["PageNumber"] = NewPageNumber;txtGridViewPageNumber.Text = Session["PageNumber"].ToString();GetAndBindData(Convert.ToInt32(Session["PageNumber"]), 10);btnGridViewPrevious.Enabled = true;
}protected void btnGridViewGoToPageNumber_Click(object sender, EventArgs e)
{Int32 NewPageNumber = Convert.ToInt32(txtGridViewPageNumber.Text);Session["PageNumber"] = NewPageNumber;txtGridViewPageNumber.Text = Session["PageNumber"].ToString();GetAndBindData(Convert.ToInt32(Session["PageNumber"]), 10);btnGridViewPrevious.Enabled = true;
}

要点总结

通过此方法,在用户改变页面索引时,开发者可以只获取相关数据进行展示,而非完整的数据集。这样,不仅可以从数据库中选出相关数据,在 GridView 中过滤数据所需的步骤也可以避免。从而切实提高并优化应用性能。

原文地址:http://www.codeproject.com/Articles/1078...

OneAPM 助您轻松锁定 .NET 应用性能瓶颈,通过强大的 Trace 记录逐层分析,直至锁定行级问题代码。以用户角度展示系统响应速度,以地域和浏览器维度统计用户使用情况。想技术文章,请访问 OneAPM 官方博客。
本文转自 OneAPM 官方博客

ASP .NET 如何在 SQL 查询层面实现分页 1相关推荐

  1. ASP .NET 如何在 SQL 查询层面实现分页

    [编者按]本文作者为来自巴基斯坦的软件开发工程师 Aqeeel,主要介绍了在 SQL 查询层面实现 ASP.NET 应用的分页方法. 本文系 OneAPM 工程师编译呈现,以下为正文. GridVie ...

  2. oracle查数据存入数组,如何在SQL查询中使用Oracle关联数组

    ODP.Net公开了将关联数组作为参数从C#传递到Oracle存储过程的能力.除非您尝试在sql查询中使用该关联数组中包含的数据,否则它是一个很好的功能. 原因是它需要上下文切换 – SQL语句需要S ...

  3. 代码日常--如何在SQL查询语句中添加判断逻辑

    前景提要:查询某个商品是否参加推广,表product_channel,字段distribute_status. Y表示参与,N表示不参与,但由于该字段是新添加,默认为null,所以null也属于不参与 ...

  4. 如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集

    如何在SQL Server查询语句(Select)中检索存储过程(Store Procedure)的结果集?(2006-12-14 09:25:36) 与这个问题具有相同性质的其他描述还包括: 如 ...

  5. 用于存储过程的ASP.NET Core Blazor和EF Core原始SQL查询

    目录 介绍 背景 先决条件 使用代码 创建数据库和表 步骤1:创建ASP.NET Core Blazor服务器应用程序 运行测试应用程序 步骤2:安装软件包 连接字符串 步骤3:建立模型类 创建DBC ...

  6. oracle中begin end的作用,如何在SQL * Plus中使用begin/end运行Oracle查询?

    我已经用begin/end创建了一个查询块,并且想要在SQL * Plus中运行它.但是我怎样才能在命令行中运行它?如何在SQL * Plus中使用begin/end运行Oracle查询? 其实代码来 ...

  7. asp mysql datetime_ASP中SQL和Access数据库中时间/日期字段内容查询的方法说明

    方法如下: MS SQL数据库: SQL="select * from 表名 where 时间/日期字段 between '"& 传递过来开始的时间值 &" ...

  8. asp sql查询过滤空格_对比Excel,轻松学习SQL数据分析数据笔记02

    本文主要梳理<对比Excel,轻松学习SQL数据分析>对于自己有用的sql知识.这本书中的所有代码和函数均适用于my sql 8.0版本. SQL的基本功能数据定义(DDL)--对数据库, ...

  9. sql查询禁用缓存_如何在SQL Server 2017中启用和禁用身份缓存

    sql查询禁用缓存 Every data warehouse developer is likely to appreciate the significance of having surrogat ...

最新文章

  1. 利用脑机接口提高意念打字速度,让新手用户也能快速上手意念交流
  2. “毕设导师互选系统”项目产品宣传推广方案
  3. oracle中用START WITH...CONNECT BY PRIOR子句实现递归查询
  4. FullCalendar插件月视图正常显示周视图不正常显示问题解决方法
  5. C Primer Plus 第8章 字符输入/输出和输入确认 8.1 单字符I/O
  6. 内存cookie与持久cookie
  7. Emmet 快速编写html代码
  8. STM32工作笔记0094---音乐播放器实验
  9. Json-lib, 实现Java对象与JSON数据格式的互转
  10. g++是什么_路由器信号分为2.4G和5G,有什么区别?怎么选?
  11. Spring AOP(二)之AfterReturning增强处理
  12. 高通工具QXDM、QCAT和QPST
  13. 电脑外接显示器或ipad分屏
  14. 计算机上没有端口DOT4,hp1010win7系统打印机装不了dot4端口没反应
  15. android 实现拍照,android 实现拍照的2种方法
  16. 移动端适配多种方案详细分析
  17. 神经网络图像细节分析,神经网络 图像相似度
  18. 干货满满!25种绝佳VSCode扩展,体验便捷高效的生活
  19. PHP项目快速接入微信功能
  20. python常用字体显示方框_seaborn模块中,图表中文字体变成方块的问题如何解决?...

热门文章

  1. 米家扫地机器人是石头代工_扫地机器人“两强”突进,选科沃斯还是石头科技?...
  2. C++socket编程(七):7.3 http的响应协议
  3. oracle session status killed,进程状态为KILLED的进程如何杀掉
  4. 原子变量的原理与应用
  5. linux网卡ip自动启动不了怎么办,Linux杂谈:解决配置静态ip后eth0网卡启动不了的问题...
  6. python 多进程 内存增长_python 多进程 内存 copy-on-write
  7. python 脚本传参
  8. opencv 图像属性
  9. 机器学习实战(MachineLearinginAction) 第二章 k-近邻算法
  10. git 理解 HEAD^与HEAD~