|
先說說數(shù)據(jù)分頁(yè)的原理。我們?cè)陂_發(fā)數(shù)據(jù)綁定頁(yè)面的Web應(yīng)用程序時(shí),常常會(huì)遇到數(shù)據(jù)量比較多的情況,為了防止頁(yè)面變得過大加載數(shù)據(jù)慢的問題,大家都會(huì)將一個(gè)頁(yè)面上要顯示的數(shù)據(jù)通過分頁(yè)來完成,用戶訪問頁(yè)面時(shí)通過分頁(yè)功能來查看不同頁(yè)面中的數(shù)據(jù),這是一個(gè)非常好的解決辦法,而且?guī)缀跛械某绦蛟O(shè)計(jì)人員和開發(fā)人員都會(huì)不約而同樂此不彼地采用分頁(yè)的方式來顯示頁(yè)面上的數(shù)據(jù),這沒有什么問題! 問題在于分頁(yè)的方式。
一般情況下,最簡(jiǎn)單的實(shí)現(xiàn)方法是一次性將所有頁(yè)面的數(shù)據(jù)讀到緩存媒介中(這個(gè)媒介一般都是服務(wù)器的內(nèi)存),然后每次只顯示一頁(yè)的數(shù)據(jù)。這種方式實(shí)現(xiàn)起來很容易,而且ASP.NET之前幾乎所有的支持分頁(yè)的數(shù)據(jù)綁定控件都是采用的這種方式,以至于很多ASP.NET的初學(xué)者都采用了這樣的方式來開發(fā)分頁(yè)數(shù)據(jù)綁定頁(yè)面,并且沒有覺察出任何問題。是的,程序開發(fā)中采用最簡(jiǎn)單有效的方法一般都是不會(huì)出現(xiàn)什么問題的,況且微軟提供的標(biāo)準(zhǔn)控件都是這樣做的,會(huì)有什么問題呢?對(duì)于一些小的Web應(yīng)用程序而言,這確實(shí)沒有什么問題,因?yàn)樗婕暗降臄?shù)據(jù)量比較小,即使我們將所有的數(shù)據(jù)都讀到內(nèi)存中,充其量也才幾兆,多一點(diǎn)十幾兆,幾十兆。如果這些數(shù)據(jù)都是純文本的話(一般而言我們保存在數(shù)據(jù)庫(kù)中的數(shù)據(jù)都是文本信息),幾十兆的數(shù)據(jù)已經(jīng)是成千上萬條記錄了,現(xiàn)在的服務(wù)器硬件條件都比較好,內(nèi)存都在G級(jí)以上,處理這點(diǎn)數(shù)據(jù)根本不在話下。但是,如果數(shù)據(jù)庫(kù)中的一個(gè)表的記錄達(dá)到上億條,并且有些字段存儲(chǔ)的是文件數(shù)據(jù)(也就是二進(jìn)制數(shù)據(jù)),這樣一次性將所有的數(shù)據(jù)讀到內(nèi)存中就不是一個(gè)理想的做法了,這個(gè)時(shí)候就需要采用“真分頁(yè)”方式讀取數(shù)據(jù)。
大部分情況下,我們還是需要采用“真分頁(yè)”的方式來獲取數(shù)據(jù)的。給定每頁(yè)記錄的起始位置(或者頁(yè)面的索引),再給定一個(gè)每頁(yè)顯示的數(shù)據(jù)的條數(shù)和總記錄數(shù),我們希望每次取到的只是當(dāng)前頁(yè)面的數(shù)據(jù)。每次當(dāng)用戶分頁(yè)時(shí),根據(jù)這些條件從數(shù)據(jù)庫(kù)中取一部分?jǐn)?shù)據(jù)綁定到頁(yè)面上,這樣可以大大減少服務(wù)器的開銷,并且再大的數(shù)據(jù)量也不是問題。這種方式似乎是理想的,然而結(jié)合用戶的需求,我們會(huì)發(fā)覺即使采用“真分頁(yè)”方式對(duì)數(shù)據(jù)進(jìn)行分頁(yè)獲取,也還是會(huì)遇到問題。試想,在當(dāng)今Ajax橫行的Web世界里,利用Ajax方式改善用戶體驗(yàn)的站點(diǎn)層出不窮,如果你恰好有一個(gè)采用Ajax方式提供的分頁(yè)數(shù)據(jù)綁定頁(yè)面,那問題就會(huì)出現(xiàn)了。由于Ajax的用戶體驗(yàn)效果是頁(yè)面的局部刷新,在分頁(yè)數(shù)據(jù)綁定頁(yè)面中,用戶點(diǎn)擊分頁(yè)按鈕后頁(yè)面會(huì)以較快的速度更新分頁(yè)后的數(shù)據(jù),這個(gè)體驗(yàn)對(duì)用戶來說是相當(dāng)不錯(cuò)的,但是貪婪的用戶有可能會(huì)想試試頻繁地點(diǎn)擊分頁(yè)按鈕,甚至于瘋狂的用戶狂點(diǎn)分頁(yè)按鈕,這個(gè)時(shí)候你的應(yīng)用程序由于需要非常頻繁地去數(shù)據(jù)庫(kù)中獲取分頁(yè)數(shù)據(jù)而來不及更新頁(yè)面上的數(shù)據(jù)而出現(xiàn)腳本錯(cuò)誤,最終給用戶的體驗(yàn)就是頁(yè)面的分頁(yè)功能不正常,程序崩潰了。
采用“真分頁(yè)”和“假分頁(yè)”相結(jié)合的方式可以很有效得解決上面提到的這個(gè)問題。我將上面提到的第一種數(shù)據(jù)分頁(yè)方式稱之為“假分頁(yè)”,而將第二種數(shù)據(jù)分頁(yè)方式稱之為“真分頁(yè)”。這兩種分頁(yè)方式的結(jié)合,就是說一次性讀取n頁(yè)的數(shù)據(jù)到緩存中,分頁(yè)時(shí)根據(jù)需要判斷是否從緩存中直接獲取數(shù)據(jù)還是重新從數(shù)據(jù)庫(kù)中加載數(shù)據(jù)到緩存里。畢竟,從緩存中加載數(shù)據(jù)效率要高得多。這樣,每次用戶點(diǎn)擊分頁(yè)按鈕時(shí),只要數(shù)據(jù)存在于緩存里,就可以以非??斓乃俣燃虞d數(shù)據(jù),如果緩存過期或者用戶要獲取的數(shù)據(jù)超出了緩存,就從數(shù)據(jù)庫(kù)中重新加載新的n頁(yè)數(shù)據(jù)到緩存中。當(dāng)然,更新緩存的過程你可以在Ajax中采用同步采用,以限制用戶在這個(gè)過程中的UI操作。
其實(shí),分頁(yè)中所涉及到的細(xì)節(jié)問題是很多的,要想詳細(xì)敘述并講清楚這其中的所有問題,光靠本文的只言片語恐怕是遠(yuǎn)遠(yuǎn)不夠的,這里我只想向大家介紹一種在ASP.NET Ajax方式下進(jìn)行真分頁(yè)編程的一種方法。為了比較簡(jiǎn)單地使用Ajax方式,我在Visual Studio中直接使用了微軟提供的ajaxToolkit包里的Ajax控件,這些控件一般來說都還是挺好用的,這里不對(duì)這些控件的使用做介紹了。
在寫這篇文章之前我也查閱了很多資料,其實(shí)大家在開發(fā)數(shù)據(jù)綁定頁(yè)面時(shí)一般都會(huì)采用“真分頁(yè)”的方式來對(duì)數(shù)據(jù)進(jìn)行分頁(yè)處理,ASP.NET 3.5中的DataPager控件是一個(gè)用于數(shù)據(jù)分頁(yè)的不錯(cuò)的控件,有的人把微軟提供的數(shù)據(jù)綁定控件不支持?jǐn)?shù)據(jù)“真分頁(yè)”的缺陷歸到它的頭上,我認(rèn)為這是對(duì)它的冤枉。DataPager只負(fù)責(zé)分頁(yè)操作,它不管數(shù)據(jù)源的事情,它更重要的工作在于如何處理分頁(yè)UI以及與用戶的交互。那么,數(shù)據(jù)源怎么處理呢?數(shù)據(jù)綁定控件如何知道我的數(shù)據(jù)源被分成了多少頁(yè),我當(dāng)前取的是哪一頁(yè)的數(shù)據(jù)呢?
這些問題也一度讓我很苦惱,我嘗試過使用.NET中的PagedDataSource對(duì)象對(duì)數(shù)據(jù)進(jìn)行分頁(yè),但是后來發(fā)覺這個(gè)對(duì)象也是需要一次性將所有的數(shù)據(jù)讀到內(nèi)存中才支持分頁(yè)的,說白了,它也是一個(gè)“假分頁(yè)”數(shù)據(jù)源對(duì)象,和DataGrid、GridView沒有什么不同。記得從.NET 2.0開始,微軟提供了一系列數(shù)據(jù)源控件(諸如SqlDataSource、XmlDataSource、LinqDataSource等等)來簡(jiǎn)化對(duì)數(shù)據(jù)綁定控件的數(shù)據(jù)源指定,其實(shí)我覺得這些控件除了簡(jiǎn)化代碼外沒有什么大的價(jià)值,有的時(shí)候還會(huì)破壞程序本身的結(jié)構(gòu),我一向都反對(duì)在頁(yè)面上直接使用這些控件(當(dāng)然,做一些演示用的程序使用這些控件還是非常便捷的)。不過我在研究Ajax真分頁(yè)的過程中無意間看到了Visual Studio工具箱中的ObjectDataSource這個(gè)控件,起初我只是認(rèn)為它應(yīng)該是那些DataSource控件的基控件,后來通過查資料才知道,這個(gè)控件是所有的DataSource控件中唯一支持“真分頁(yè)”操作的控件,它可以通過設(shè)定幾個(gè)簡(jiǎn)單的屬性就達(dá)到數(shù)據(jù)分頁(yè)的功能,下面我就向大家介紹一下如何使用這個(gè)控件。
這個(gè)控件的使用很簡(jiǎn)單,我們只需要配置幾個(gè)屬性就可以了。
SelectMethod:指定用于獲取分頁(yè)數(shù)據(jù)的方法名。這個(gè)方法是一個(gè)自定義的.NET方法,你可以寫在頁(yè)面的CodeBehind代碼中,將方法的名字給ObjectDataSource控件的SelectMethod即可。ObjectDataSource控件會(huì)通過委托的方式自動(dòng)去執(zhí)行你所指定的這個(gè)方法。
TypeName:使用ObjectDataSource控件的類的全名稱(包括名稱空間和類名)。這個(gè)屬性必須指定,ASP.NET會(huì)通過反射來加載相應(yīng)的方法和對(duì)象。
DataObjectTypeName:數(shù)據(jù)源對(duì)象的類型全名稱。ObjectDataSource控件最大的亮點(diǎn)就在于它完全支持面向?qū)ο髷?shù)據(jù)操作。在分層應(yīng)用程序開發(fā)中,數(shù)據(jù)訪問層的代碼會(huì)將數(shù)據(jù)庫(kù)中的表抽象為class對(duì)象,將數(shù)據(jù)庫(kù)表中的字段抽象為class對(duì)象中的屬性,DataObjectTypeName屬性所指定的就是這個(gè)數(shù)據(jù)庫(kù)類對(duì)象。
EnablePaging:如果你想開啟數(shù)據(jù)分頁(yè)功能,就需要將這個(gè)屬性的值設(shè)置為True。
MaximumRowsParameterName:這個(gè)屬性的值是一個(gè)參數(shù)名(只是一個(gè)參數(shù)名,而不是每頁(yè)顯示的數(shù)據(jù)條數(shù)),用于指示每頁(yè)要顯示數(shù)據(jù)的條數(shù),ObjectDataSource控件根據(jù)委托在之前SelectMethod屬性所指定的方法中傳遞該參數(shù)并執(zhí)行其中的代碼。注意,這個(gè)參數(shù)的名稱必須與SelectMethod屬性所指定的方法中的參數(shù)名稱完全一樣。
StartRowIndexParameterName:這個(gè)屬性也是一個(gè)參數(shù)名,用于指示每頁(yè)起始記錄的索引。用法與MaximumRowsParameterName相同。
SelectCountMethod:這個(gè)屬性是一個(gè)方法的簽名,用來告訴ObjectDataSource控件通過什么方式得知數(shù)據(jù)源中總記錄的條數(shù)。ObjectDataSource控件同樣通過委托來執(zhí)行這個(gè)方法,所以方法的簽名必須與屬性的值完全一樣。
然后我們?cè)陧?yè)面上放置一個(gè)ListView控件(或者其它任何一個(gè)數(shù)據(jù)綁定控件),將它的DataSourceID屬性的值設(shè)置為ObjectDataSource的ID,然后添加一個(gè)DataPager控件,將PagedControlID屬性的值設(shè)置為L(zhǎng)istView的ID。
這是我所取的數(shù)據(jù)源中的三張數(shù)據(jù)表的結(jié)構(gòu)關(guān)系圖,其中主表是Shoutout表,Shoutout中的一條記錄對(duì)應(yīng)著多個(gè)Image,它們通過BaseComment表進(jìn)行關(guān)聯(lián)。在下面我會(huì)給出如果獲取Shoutout分頁(yè)數(shù)據(jù)的存儲(chǔ)過程的代碼。
復(fù)制代碼 代碼如下:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AllShoutout.ASPx.cs" Inherits="ShoutoutWallTest.AllShoutout" %>
<%@ Register Assembly="AjaxControlToolkit, Version=3.0.20820.415, Culture=neutral, PublicKeyToken=28f01b0e84b6d53e"
Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
<link href="Css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<form id="form1" runat="server">
<ASP:ScriptManager ID="ScriptManager1" runat="server">
</ASP:ScriptManager>
<div id="shoutoutall">
<div style="float: left;">
<ASP:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<ASP:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="LoadShoutouts"
TypeName="ShoutoutWallTest.AllShoutout" DataObjectTypeName="Model.Shoutout" EnablePaging="True"
MaximumRowsParameterName="maxRows" StartRowIndexParameterName="startIndex" SelectCountMethod="CountAll"></ASP:ObjectDataSource>
<div id="shoutoutalldescription">
<ASP:ListView ID="lvShoutout" DataSourceID="ObjectDataSource1" runat="server" ItemPlaceholderID="layoutTableTemplate"
DataKeyNames="ID" OnItemDataBound="lvShoutout_ItemDataBound">
<LayoutTemplate>
<div id="layoutTableTemplate" runat="server">
</div>
</LayoutTemplate>
<ItemTemplate>
<div class="shoutoutallcontent">
<div class="shoutoutalltext">
<%#Eval("Description") %></div>
<div>
<!--Add images here-->
<ASP:ListView ID="lvImages" runat="server" ItemPlaceholderID="layoutImages" DataSource='<%#Eval("Images")%>'>
<LayoutTemplate>
<div id="layoutImages" runat="server">
</div>
</LayoutTemplate>
<ItemTemplate>
<a href='Thumbnail.ASPx?isthumbnail=false&basecommentid=<%#Eval("BaseCommentID").ToString() %>&imagetitle=<%#Eval("Title") %>'
target="_blank">
<img src='Thumbnail.ASPx?basecommentid=<%#Eval("BaseCommentID").ToString() %>&imagetitle=<%#Eval("Title") %>'
alt="" class="shoutoutimg" /></a>
</ItemTemplate>
</ASP:ListView>
</div>
<div class="shoutoutallposted">
Posted by:<%#Eval("PostedByName") %> <%#((DateTime)Eval("PostedDate")).ToShortDateString() %></div>
<div class="shoutoutallfooter">
<ASP:Button ID="btEdit" CssClass="shoutoutalllistbutton" OnClick="btEdit_Click" runat="server"
Text="Edit" />
<ASP:Button ID="btDel" CssClass="shoutoutalllistbutton" OnClick="btDel_Click" runat="server"
Text="Delete" OnClientClick="return confirm('Are you sure delete it?');" />
</div>
</div>
</ItemTemplate>
</ASP:ListView>
</div>
<div class="shoutoutallfooter">
<ASP:DataPager ID="DataPager1" runat="server" PagedControlID="lvShoutout" PageSize="25">
<Fields>
<ASP:NextPreviousPagerField ButtonType="Image" FirstPageText="Go to first page" FirstPageImageUrl="./Images/ShoutOut_ViewAll_Left.gif" ShowFirstPageButton="true" ShowNextPageButton="false"
ShowPreviousPageButton="false" />
<ASP:NumericPagerField NumericButtonCssClass="shoutoutallnumericpager" ButtonType="Button" PreviousPageImageUrl="./Images/ShoutOut_ViewAll_Left.gif" NextPreviousButtonCssClass="shoutoutallnextprepager" NextPageText=">>" PreviousPageText="<<" CurrentPageLabelCssClass="shoutoutallcurrentpager" ButtonCount="5" />
<ASP:NextPreviousPagerField ButtonType="Image" LastPageText="Go to last page" LastPageImageUrl="./Images/ShoutOut_ViewAll_Right.gif" ShowLastPageButton="true" ShowNextPageButton="false"
ShowPreviousPageButton="false" />
</Fields>
</ASP:DataPager>
</div>
</ContentTemplate>
</ASP:UpdatePanel>
</div>
</div>
</form>
</body>
</html>
我把數(shù)據(jù)綁定控件和分頁(yè)控件都放在UploadPanel控件中,這樣頁(yè)面就會(huì)在不刷新的情況下執(zhí)行數(shù)據(jù)綁定和分頁(yè)操作。代碼中使用了一個(gè)嵌套的ListView,原因是一條Shoutout記錄會(huì)對(duì)應(yīng)多條image記錄,結(jié)合數(shù)據(jù)層的數(shù)據(jù)實(shí)體類,Shoutout class中會(huì)有一個(gè)類似于List<Image> Images的屬性,所以我直接將這個(gè)屬性作為了子ListView控件的數(shù)據(jù)源,它主要用于顯示每條Shoutout記錄中的縮略圖。至于如何在頁(yè)面中顯示縮略圖不是本文的重點(diǎn),這里不做介紹了。代碼中我們已經(jīng)給ObjectDataSource控件指定了用于進(jìn)行數(shù)據(jù)分頁(yè)的參數(shù)名或方法簽名,下面我們需要實(shí)現(xiàn)這些方法。
只有兩個(gè)方法,LoadShoutouts()方法用于獲取數(shù)據(jù)對(duì)象Shoutout的集合,也就是List<Shoutout>類型的返回值,事實(shí)上,該方法只需要執(zhí)行數(shù)據(jù)庫(kù)中用于分頁(yè)的存儲(chǔ)過程即可,這個(gè)存儲(chǔ)過程可以同時(shí)返回?cái)?shù)據(jù)集合和總記錄條數(shù)。下面我會(huì)給出這個(gè)存儲(chǔ)過程。CountAll()方法僅僅只返回總的記錄條數(shù)。
復(fù)制代碼 代碼如下:
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections.Generic;
using Model;
using BLL;
namespace ShoutoutWallTest
{
public partial class AllShoutout : System.Web.UI.Page
{
public static List<Shoutout> list = null;
private static int ItemCount = 0;
protected void Page_Load(object sender, EventArgs e)
{
}
public List<Shoutout> LoadShoutouts(int startIndex, int maxRows)
{
int itemCount;
int pageIndex = 1;
if (startIndex > 0)
{
pageIndex = (startIndex) / 25 + 1;
}
list = ShoutoutBLL.GetShoutouts(13, pageIndex, maxRows, true, out itemCount);
ItemCount = itemCount;
return list;
}
public int CountAll()
{
return ItemCount;
}
/// <summary>
/// Refresh data after updating and deleting.
/// </summary>
private void RefreshData()
{
lvShoutout.DataSourceID = ObjectDataSource1.ID;
}
}
}
我的代碼中要求每頁(yè)顯示25條數(shù)據(jù),ShoutoutBLL.GetShoutouts()方法有5個(gè)參數(shù),第一個(gè)參數(shù)用于指定檢索數(shù)據(jù)的條件,這個(gè)是程序中的特例,讀者可以不用關(guān)心;第二個(gè)參數(shù)是頁(yè)面的索引,規(guī)定從1開始,我在方法中從startIndex轉(zhuǎn)換成了pageIndex;第三個(gè)參數(shù)是每頁(yè)顯示的數(shù)據(jù)條數(shù);第四個(gè)參數(shù)是out類型的,返回記錄總行數(shù),這個(gè)方法主要是為了對(duì)應(yīng)執(zhí)行數(shù)據(jù)庫(kù)的存儲(chǔ)過程,具體代碼在BLL命名空間中,屬于業(yè)務(wù)邏輯層的代碼,這里就不再具體給出了,Model命名空間中的代碼主要用來返回?cái)?shù)據(jù)庫(kù)實(shí)體對(duì)象,如Shoutout和Image對(duì)象。RefreshData()方法中重新給ListView控件的DataSourceID屬性指定了值,這樣可以重新綁定數(shù)據(jù)從而達(dá)到刷新數(shù)據(jù)的效果。 上圖是程序運(yùn)行后的部分截圖,可以看出分頁(yè)UI已經(jīng)顯示出來了,而且對(duì)于分頁(yè)操作,我沒有寫一行代碼,這個(gè)完全由DataPager自己來控制。由于ListView和DataPager控件都位于UpdatePanel控件中,當(dāng)用戶點(diǎn)擊分頁(yè)按鈕時(shí)頁(yè)面只是更新了ListView中的數(shù)據(jù)而沒有刷新整個(gè)頁(yè)面,并且數(shù)據(jù)是逐頁(yè)從數(shù)據(jù)庫(kù)中得到的,這樣便實(shí)現(xiàn)了在Ajax方式下的“真分頁(yè)”操作。核心控件是ObjectDataSource。下面是我用于獲得分頁(yè)數(shù)據(jù)的存儲(chǔ)過程,讀者可以借鑒一下,這個(gè)存儲(chǔ)過程采用了臨時(shí)表的方式進(jìn)行數(shù)據(jù)分頁(yè)。
復(fù)制代碼 代碼如下:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[GetShoutOuts]
-- Add the parameters for the stored procedure here
(
@LocationID INT,
@PageIndex INT, -- start from 1.
@PageSize INT,
@showimages BIT,
@ItemCount INT Output
)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare @beginRowNumber bigint,@endRowNumber bigint
set @beginRowNumber = (@PageIndex - 1)*@PageSize+1;
set @endRowNumber = @PageIndex*@PageSize;
WITH TempPagingRecord AS
(
SELECT ROW_NUMBER() OVER(ORDER BY PostedDate DESC) AS RecordNumber,SO.ID AS ShoutOutID, BC.[Description], BC.PostedByName, BC.PostedDate,null as ImageTitle,null as ImageBlob,null as Type,BC.ID AS BaseCommentID,BC.DisplayUserName,
BC.IsVisible, SO.NotifyToShoutOutUser, SO.ShoutOutToUserAlias
FROM dbo.ShoutOut as SO
JOIN dbo.BaseComment as BC ON BC.ID = SO.BaseCommentID
WHERE SO.LocationID =@LocationID
AND BC.IsVisible = 1
)
SELECT RecordNumber,
ShoutOutID,
Description,
PostedByName,
PostedDate,
ImageTitle,
ImageBlob,
BaseCommentID,
DisplayUserName,
IsVisible,
NotifyToShoutOutUser,
ShoutOutToUserAlias
INTO #tempTable
FROM TempPagingRecord
Where RecordNumber between @beginRowNumber and @endRowNumber
-- Insert statements for procedure here
IF(@showimages = 1)
begin
select RecordNumber,
ShoutOutID,
Description,
PostedByName,
PostedDate,
IM.ImageTitle,
IM.ImageBlob,
IM.Type,
T.BaseCommentID,
DisplayUserName,
IsVisible,
NotifyToShoutOutUser,
ShoutOutToUserAlias from #tempTable T
Left join dbo.Image IM ON IM.BaseCommentID = T.BaseCommentID
order by PostedDate DESC
end
ELSE
begin
SELECT * FROM #tempTable
order by PostedDate DESC
end
SELECT @ItemCount = Count(*)
FROM Shoutout as SO
JOIN dbo.BaseComment as BC ON BC.ID = SO.BaseCommentID
WHERE SO.LocationID =@LocationID
AND BC.IsVisible = 1
END
個(gè)人覺得ObjectDataSource控件是一個(gè)比較智能化的控件,它通過函數(shù)委托的方式自動(dòng)執(zhí)行用戶提供的分頁(yè)代碼來完成數(shù)據(jù)庫(kù)的“真分頁(yè)”操作,省去了開發(fā)過程中的很多麻煩,還是很有必要去認(rèn)真研究一下的。
AspNet技術(shù):asp.net 使用ObjectDataSource控件在ASP.NET中實(shí)現(xiàn)Ajax真分頁(yè),轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。