在上篇
介绍了ObjectDataSource的常规使用。

上次一个网友希望介绍一下自定义分页的问题,本文说明如何使用ObjectDataSource自定义分页、排序,你会发现ObjectDataSource的伸缩性很大,。不管是初学者还是具有一定经验的用户,ObjectDataSource总能够给你提供能够满足你要求的功能。

 

    在数据分页中,最简单是利用GridView的分页、排序功能,此功能不几乎应该是确实不需要编写代码,稍微勾勾划划就能够分页、排序。然而当数据量很少时,以来此方法确实可以减轻程序员的负担,但是当数据很多,例如记录几十万、上百万时,使用系统自带的分页将导致大量数据回复,因此使用自定义分页就显得更为有效。

概括起来,天天总结自定义数据分页主要包含四种方式:

1) 使用临时表――此方法被广泛使用论坛CommunityServer、博客等开源代码

) 使用存储过程――这个方法好像最初来自上的一篇,可以到如下网址查看

3) 利用SQL语句选取有限数据分页,此方法我用过,感觉有一些问题,还有待进一步证实。
4) 可以利用GirdView的客户端到服务器的回调获得新页的数据,这是ASP.NET2.0新增的一个功能。

 

本文主要介绍第一种使用临时表进行分页。以后会介绍其它方式

 

下面是对上面文章的更改。代码如下,使用临时表进行自定义分页:

 

public List<Product> LoadAllProduct(int startIndex, int maxRows, string sortedBy)
 
    {
 
        List<Product> products = new List<Product>();
 
            SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
 
           
 
    string commandText = @"
 
     -- 为分页建立一张临时表
 
    CREATE TABLE #TempPageTable
 
    (
 
        IndexId int IDENTITY (0, 1) NOT NULL,
 
         id int   
 
     )
 
 
 
    -- 读取数据插入临时表
 
    INSERT INTO #TempPageTable
 
     (
 
         [id]
 
     )
 
     SELECT
 
         [Productid]   
 
     FROM Products";
 
 
 
 
 
 
 
         if (sortedBy != "")
 
        {
 
              commandText += " ORDER BY " + sortedBy;
 
         }
 
 
 
         commandText += @"
 
    SET @totalRecords = @@ROWCOUNT
 
 
 
      
 
    SELECT
 
         src.[ProductID],
 
         src.[ProductName],
 
         src.[CategoryID],
 
         src.[Price],
 
        src.[InStore],
 
        src.[Description]  
 
     FROM Products src, #TempPageTable p
 
     WHERE 
 
         src.[productid] = p.[id] AND
 
        p.IndexId >= @StartIndex AND p.IndexId < (@startIndex + @maxRows)";
 
        
 
        if (sortedBy != "") {
 
              commandText += " ORDER BY " + sortedBy;
 
         }
 
 
 
         SqlCommand command = new SqlCommand(commandText, conn);
 
         command.Parameters.Add(new SqlParameter("@startIndex", startIndex));
 
         command.Parameters.Add(new SqlParameter("@maxRows", maxRows));
 
         command.Parameters.Add(new SqlParameter("@totalRecords", SqlDbType.Int));
 
         command.Parameters["@totalRecords"].Direction = ParameterDirection.Output;
 
 
 
         conn.Open();
 
         SqlDataReader dr = command.ExecuteReader();
 
         while (dr.Read()) {
 
              Product prod = new Product();
 
 
 
              prod.ProductID = (int)dr["ProductID"];
 
              prod.ProductName= (string)dr["ProductName"];
 
            prod.CategoryID = (int)dr["CategoryID"];
 
              prod.Price = (decimal)dr["price"];
 
            prod.InStore=(Int16)dr["InStore"];
 
            prod.Description=(String)dr["Description"];
 
              products.Add(prod);
 
         }
 
 
 
         dr.Close();
 
         conn.Close();
 
 
 
         _count = (int)command.Parameters["@totalRecords"].Value;
 
 
 
         return products;
 
     }
 
 
 
 
 
    public int CountAll()
 
    {
 
        return _count;
 
    }

简单解释如下:
1)这里定义了一个临时表 #TempPageTable,临时表的定义需要加“#”,临时表的好处是自动创建,并在不需要时候进行销毁。具体介绍请参考SQL的帮助系统。
2)在临时表里我建立了一个索引印列IndexId和id列。如果你查看我的数据库Producst表的设计可以看到该表包含一个ProductID列,该列是一个自增型标识种子,那么为什么还需要建立IndexId列?
这是因为Product表的ProductID列是一个自增形式,所以序号将会在你编辑时可能会打乱,例如原来产品记录是1,2,3,4,5后来你删除了一条记录,例如5,那么当你再增加一条记录时,新的序列号将是从6开始,而不会使用原来的5。
为了让索引不断号的自增,使用了自定义了自增的IndexId临时表。
3)临时表里的id列对应ProductID,正如你看到的,该id列插入的数据实际上来自Products表的ProductID列

 

    
下面是在页面使用的源代码:

 

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="LoadAllProduct" TypeName="ProductBLL" DataObjectTypeName="Product"
 
        EnablePaging="True" MaximumRowsParameterName="maxRows" StartRowIndexParameterName="startIndex" SelectCountMethod="CountAll" SortParameterName="sortedBy"
 
        ></asp:ObjectDataSource>
 
          <asp:GridView ID="GridView1" runat="server" CellPadding="4" Font-Names="Verdana"
 
            Font-Size="X-Small" ForeColor="#333333" GridLines="None" DataSourceID="ObjectDataSource1" AllowPaging="True" AllowSorting="True">
 
            <FooterStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />

 

具体的解释请自己研究吧。

单击此处源代码下载:/Files/mqingqing123/ObjectDataSourceExample.rar
使用VS.NET2005或者VWD2005以“File System”放置打开,可以直接运行本文源代码。
 

 

 

 

 

 

ObjectDataSource提供了六个参数列表占位符号,除此以外,还可以自定义自己的参数列表,如下:
1

<SelectParameters><asp:QueryStringParameter Name="CategoryName" QueryStringFiled="CategoryName" />
        <XXXX:MyCustomParam Name="Param2" SomeAttribute="SomeValue" />
</SelectParameters>

请注意上面粗体字体,它就是自定义的模式,如果要自定义参数列表,需要如下步骤
1)从Parameter派生
public class MyParameter : System.Web.UI.WebControls.Parameter

2)重载Evaluate和Clone方法

protected override object Evaluate(HttpContext context, Control control)
{
   return "My value";
}
 
 
protected override Parameter Clone()
{
    return new MyParameter(this);
}



下面是一个示例,来自国外一个人的博客

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
 
namespace ClassLibrary1
{
    public class MyParameter : Parameter
    {
        public MyParameter(string name, object value) : base(name)
        {
            this.MyProperty = value;
        }
 
 
        public MyParameter(string name, TypeCode type, object value) : base(name, type)
        {
            this.MyProperty = value;
        }
 
 
        protected MyParameter(MyParameter original) : base(original)
        {
            this.MyProperty = original.MyProperty;
        }
 
 
        protected override object Evaluate(HttpContext context, Control control)
        {
            return "My value";
        }
 
 
        protected override Parameter Clone()
        {
            return new MyParameter(this);
        }
 
 
        public string MyProperty
        {
            get
            {
                object obj = base.ViewState["MyProperty"];
 
                if (obj == null)
                    return string.Empty;
 
                return (string)obj;
            }
            set
            {
                if (this.MyProperty != value)
                {
                    base.ViewState["MyProperty"] = value;
                    base.OnParameterChanged();
                }
            }
        }
     }
}