Web Pages - Efficient Paging Without The WebGrid

If you want to display your data over a number of pages using WebMatrix Beta1, you have two options. One is to use the built-in paging support that comes with the WebGrid helper. But that means that your data will be displayed within an HTML table. If that is not your preferred layout choice, you need to write your own paging code. Let's look at how you can do that.

Actually, there is another problem with paging within the WebGrid helper apart from being restricted to html tables, and that is that's it's not particularly efficient out of the box. If you have 10,000 rows of data, and you want to display 10 rows per page, all 10,000 rows are retrieved from the database for each page. The pager works out how to only show the current 10, and wastes the other 9,990 rows. That's a fair sized overhead on each page. Ideally, you should only retrieve the data you need for each page. Sql Server CE 4.0 offers OFFSET and FETCH, which enable paging queries.

I'm going to add a page to the Books application I introduced in my first look at WebMatrix. I've called it Paging.cshtml. If you followed the second of my WebMatrix articles, you should already know that I have fiddled around with the original download and added some support for layout pages and so on to create a consistent look and feel. So if you are using the download as a basis to add paging functionality, you may want to quickly look at what I described in the second article, or just go to the bottom of this article to get the updated download. Back to Paging.cshtml, I have removed all the default markup so that this page becomes a content page. At the top of the page, I declare a number of variables:

var pageSize = 3;
var totalPages = 0;
var count = 0;
var page = UrlData[0].AsInt(1);
var offset = (page -1) * pageSize;

The first variable is pageSize. This dictates how many records per page I want to display. I've set it at 3. totalPages will be used to calculate how many pages of data there are in the database that match the selection criteria. count will be used to store the total number of matching records that match the selection criteria. page is used to identify what the current page is. It will actually obtain its value from the URL of the page. I've decided to take advantage of the built in routing support that comes with Web Pages, but more of that a bit later. The current page defaults to 1 if no value is present. Finally, offset will be used to specify how many rows of data within the database should be ignored before the current "page" of data is retrieved. The calculation for offset's value is actually quite straightforward. If the current page is 1, offset will equal 1 - 1 * 3. Since that results in zero, no rows of data will be skipped. If the current page is determined to be 3, offset will equal 3 - 1 * 3 (or 6). In other words, we want to ignore rows 1 - 6 and show rows 7, 8 and 9 on page 3.

We need to get the total number of records that can be displayed, first. This will be used to calulcate the totalPages.

var db = Database.Open("Books");
var sql = "Select Count(*) From Books " +
"Inner Join Authors on Books.AuthorId = Authors.AuthorId " +
"Inner Join Categories on Books.CategoryId = Categories.CategoryId";
count = (int)db.QueryValue(sql);
totalPages = count/pageSize;
if(count % pageSize > 0){
totalPages += 1;
}

If you only want a single value returned from the database query, Database.QueryValue() is the method that should be used. It returns something of type object, which needs to be cast to the correct type (in this case an int) for you to be able to work with it. The code above simply returns a number, containing the COUNT of all matching rows in the database. That's divided by the number of records per page, and the result is the total number of full pages of 3 records available. The modulus operator (%) is also used here to calculate whether there are still records left over after the previous division because it rounds down. If there are, another page is added to totalPages to take account of these extra records.

Now we have all the elements required to calculate the pages of data needed, and which page the user is on. All that's needed is a way to pass this information to the SQL query which is responsible for getting the current page of data:

sql = "Select Title, ISBN, Description, FirstName, LastName, Category From Books " +
"Inner Join Authors on Books.AuthorId = Authors.AuthorId " +
"Inner Join Categories on Books.CategoryId = Categories.CategoryId " +
"Order By BookId OFFSET @0 ROWS FETCH NEXT @1 ROWS ONLY;"; var result = db.Query(sql, offset, pageSize);

This query shows the OFFSET and FETCH keywords in use. As I alluded to earlier, OFFSET is the starting point at which records should be retrieved, and FETCH dictates how many should be retrieved. OFFSET and FETCH need an ORDER BY clause to be able to work, so I decided to order the results by the BookId value. @0 and @1 are parameter markers. This allows for values to be passed in dynamically, and is the preferred way to pass in variable values to a SQL query.

I mentioned earlier that the current page is calculated from the URL, and that I have taken advantage of the inbuilt support that for Routing that comes with Web Pages. Now is the time to examine that in a bit more detail. Routing is a mechnism whereby URLS are mapped to resources on the web server. The whole topic deserves more explanation than I am going to give here, but fundamentally, a URL of www.mysite.com/Paging will map to www.mysite.com/Paging.cshtml. Equally, www.mysite.com/Paging/3 can be used to request page 3 of the data. The /3 part of the url is available within UrlData, which is a zero based collection. Referencing the element within the collection by its index is done by putting the index in square brackets: UrlData[indexvalue]. So UrlData[0] in this case will return the current page number from the address in the browser. So, if we run the query having requested page 3. it translates to "Get me these records, offsetting the first 6 rows, and only fetch the next 3 rows".

The next bit of code shows how the records are to be displayed, but at the top of this page, I have also added a bit of code which shows the user which page they are currently on, and how many pages there are in total:

<p>Page @page of @totalPages</p>

@foreach(var row in result){
<h2>@row.Title</h2>
<p><strong>Author:</strong> @row.FirstName @row.LastName<br />
<strong>ISBN:</strong> @row.ISBN <br/>
<strong>Description:</strong> @row.Description <br />
<strong>Category: </strong> @row.Category</p>
}

Finally, we need some paging links. These will be responsible for ensuring that the correct page number appears in the URL so that the user can navigate the records successfully.

 @{
for (var i = 1; i < totalPages + 1; i++){
<a href="/Paging/@i">@i</a>
}
}

This code sets up a counter to loop through from 1 to the total number of pages, and writes a link for each page of data. When you first run the page, by hitting F12 or clicking the Launch button, you will see the first 3 records in the database appear, and you can also see that the URL in the browser address bar is Paging.cshtml.

If you click the second paging link, you should see that change to Paging/2, and routing come into play.

Download the code from here. To run it, simply unzip the folder, and then use the Create Site From Folder option in WebMatrix.

Web Pages - Efficient Paging Without The WebGrid的更多相关文章

  1. ASP.NET Web Pages:WebGrid 帮助器

    ylbtech-.Net-ASP.NET Web Pages:WebGrid 帮助器 1.返回顶部 1. ASP.NET Web Pages - WebGrid 帮助器 WebGrid - 众多有用的 ...

  2. Web Pages razor 学习

    1. Web Pages razor Web Pages 是三种 ASP.NET 编程模型中的一种,用于创建 ASP.NET 网站和 web 应用程序. 其他两种编程模型是 Web Forms 和 M ...

  3. ASP.NET Web Pages:C# 和 VB 实例

    ylbtech-.Net-ASP.NET Web Pages:C# 和 VB 实例 1.返回顶部 1. ASP.NET Web Pages - C# 和 VB 实例 通过 C# 和 Visual Ba ...

  4. ASP.NET Web Pages:Chart 帮助器

    ylbtech-.Net-ASP.NET Web Pages:Chart 帮助器 1.返回顶部 1. ASP.NET Web Pages - Chart 帮助器 Chart 帮助器 - 众多有用的 A ...

  5. ASP.NET Web Pages:帮助器

    ylbtech-.Net-ASP.NET Web Pages:帮助器 1.返回顶部 1. ASP.NET Web Pages - 帮助器 Web 帮助器大大简化了 Web 开发和常见的编程任务. AS ...

  6. ASP.NET Web Pages (Razor) API Quick Reference

    ASP.NET Web Pages (Razor) API Quick Reference By Tom FitzMacken|February 10, 2014 Print This page co ...

  7. 如何在ASP.NET Web站点中统一页面布局[Creating a Consistent Layout in ASP.NET Web Pages(Razor) Sites]

    如何在ASP.NET Web站点中统一页面布局[Creating a Consistent Layout in ASP.NET Web Pages(Razor) Sites] 一.布局页面介绍[Abo ...

  8. Displaying Data in a Chart with ASP.NET Web Pages (Razor)

    This article explains how to use a chart to display data in an ASP.NET Web Pages (Razor) website by ...

  9. ASP.NET MVC3 系列教程 – Web Pages 1.0

    http://www.cnblogs.com/highend/archive/2011/04/14/aspnet_mvc3_web_pages.html I:Web Pages 1.0中以“_”开头的 ...

随机推荐

  1. quartz介绍

    Quartz 是一个开源的作业调度框架,它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中.它提供了巨大的灵活性而不牺牲简单性.你能够用它来为执行一个作业而创建简单的或复杂的调度.本 ...

  2. ubuntu下配置和使用ssh

    安装 sudo apt-get install openssh-server 启动.停止.重启ssh server sudo /etc/init.d/ssh start sudo /etc/init. ...

  3. 编译器角度看C++复制构造函数

    [C++对象模型]复制构造函数的建构操作 关于复制构造函数的简单介绍,可以看我以前写过的一篇文章C++复制控制之复制构造函数该文章中介绍了复制构造函数的定义.调用时机.也对编译器合成的复制构造函数行为 ...

  4. python协程和yeild

    python多线程其实在操作系统级别是进程,因为在执行时,默认加了一个全局解释器锁(GIL),python的多线程,本质还是串行的,无法利用多核的优势:在java和C# 中,多线程是并发的,可以充分利 ...

  5. 【BZOJ-3725】Matryca 乱搞

    3725: PA2014 Final Matryca Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 160  Solved: 96[Submit][St ...

  6. TYVJ1427 小白逛公园

    时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述     小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个 ...

  7. [NOIP2015] 提高组 洛谷P2615 神奇的幻方

    题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间. ...

  8. pycharm和输入法的冲突bug

    Solution:Either upgrade IBus to version 1.5.11 or add "export IBUS_ENABLE_SYNC_MODE=1" to ...

  9. python模块xlrd安装-处理excel文件必须

    我安装了很久,网上查了很多资料,但都不太适合,综合 了一下,再写一写,希望有用... 官网下载xlrd:官网xlrd下载地址, 真的很难下,我用讯雷,有时候断断续续 下面是我的百度网盘地址,分享出来, ...

  10. ecshop 给商品随机添加评论

    <?php /* * 随机插入商品评论 * * * */ define('IN_ECS', true); require(dirname(__FILE__) . '/includes/init. ...