发布使用SQL实现分页的类

cenxaoi 2003-07-23 11:16:22
本人看过,有不少人发帖问如何加快检索有几十万条记录的表显示在页面上。
看过不少人把所有记录也就是含有几十万条记录的结果集直接Fill到DataSet里面。
然后使用DataGrid的分页功能来显示几十条记录。
需知道,几十万条记录的结果集从MSSQL服务返回到Asp.Net服务就需要花费比较长的时间,Asp.Net把这几十万条记录再填充到DataSet里面要不知要花多少时间,然后DataGrid检索绑定DataTable要需要花多少时间。根据一般为提高服务速度的算法,短任务优先执行的原则。可以想象请求返回几十万条记录的线程在MSSQL和Asp.Net服务里面的优先级别比较低,更增加响应时间。更要命的是,Asp.Net的程序很多PostBack,导致提交一次,就要把上面的事情在忙一次。这样服务器很容易崩溃。
有不少人提出的解决方案是使用存储过程实现分页,这是一个好办法。但是不是所有人都会写存储过程。下面本人提供一个简单的类配置SQL语句实现分页的功能。
public class SqlPagination
{
#region Private 属性
string _Table="";
/// <summary>
/// 当前页
/// </summary>
int _CurrentPage=1;
/// <summary>
/// 每页返回多少条记录
/// </summary>
int _PageSize=1;
/// <summary>
/// 其它排序字段
/// </summary>
string _OrderField="";
/// <summary>
/// 排序关键字段,必填。
/// </summary>
string _KeyField="";
/// <summary>
/// 字段
/// </summary>
string _Fields="";
#endregion

#region Public 属性
public string Table
{
set{ _Table=value;}
get {
if(_Table=="")
throw new Exception ("Table属性不能为空");
else
return _Table;
}
}
/// <summary>
/// 当前页
/// </summary>
public int CurrentPage
{
get {return _CurrentPage;}
set
{
_CurrentPage=value;
if(_CurrentPage==0)
_CurrentPage=1;
}
}
/// <summary>
/// 每页返回多少条记录
/// </summary>
public int PageSize
{
get {return _PageSize;}
set
{
_PageSize=value;
if(_PageSize==0)
_PageSize=1;
}
}
/// <summary>
/// 其它排序字段
/// </summary>
public string OrderField
{
set {_OrderField=value;}
get { return _OrderField;}
}

/// <summary>
/// 排序关键字段,必填。
/// </summary>
public string KeyField
{
get
{
if(_KeyField.Trim()=="")
throw new Exception("缺少对KeyField属性进行赋值");
else
return _KeyField;
}
set {_KeyField=value;}
}
/// <summary>
/// 字段
/// </summary>
public string Fields
{
set {_Fields=value;}
get
{
if(_Fields.Trim()=="")
return "*";
else
return _Fields;
}
}
#endregion
#region Public字段
/// <summary>
/// 排序关键字段的数据类型,必填。
/// </summary>
public MSSqlDbType KeyFieldType;
public bool Desc=false;
public string Condition="";
#endregion

#region Public 函数
public SqlPagination(string Table,string KeyField,MSSqlDbType KeyFieldType)
{
this.Table=Table; this.KeyField=KeyField;
this.KeyFieldType=KeyFieldType;
}
/// <summary>
/// 返回分页的查询语句
/// </summary>
/// <returns></returns>
public string Select()
{
if (this.KeyFieldType==null)
throw new Exception ("KeyFieldType属性不能为空。");
string temp="";
string AndCondition="",WhereCondition="";
if (this.Condition.Trim()!="")
{
WhereCondition=" WHERE "+this.Condition;
AndCondition=" AND "+this.Condition;
}
if(!this.Desc) //升序 使用 > 不用desc 找 max
{
temp+="select top "+ this.PageSize.ToString()+ " " + this.Fields + " from "+ this.Table;
temp+=" where "+ this.KeyField +">(select isnull(max("+this.KeyField+"),"+ this.KeyFieldType.Min + ") from";
temp+=" (select top "+(this.PageSize*(this.CurrentPage-1)).ToString()+" " + this.KeyField+" from "+this.Table+WhereCondition;
temp+=" order by "+this.KeyField +") a)"+ AndCondition +" order by "+this.KeyField;
}
else
{
temp+="select top "+ this.PageSize.ToString()+ " " + this.Fields + " from "+ this.Table;
temp+=" where "+ this.KeyField +"<(select isnull(min("+this.KeyField+"),"+ this.KeyFieldType.Max + ") from";
temp+=" (select top "+(this.PageSize*(this.CurrentPage-1)).ToString()+" " + this.KeyField+" from "+this.Table+WhereCondition;
temp+=" order by "+this.KeyField +" desc) a)"+ AndCondition +" order by "+this.KeyField +" desc";
}
return temp;
}
#endregion

}
...全文
46 8 打赏 收藏 举报
写回复
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
stuhome 2003-07-26
  • 打赏
  • 举报
回复
个人认为不可取。
写的太复杂。
其实用用户控件或自定义控件是个很好的选择。
我用自己写的用户控件,核心代码也不过50多行,而且效率还很高。
sualtring 2003-07-26
  • 打赏
  • 举报
回复
收藏
niqiu322 2003-07-26
  • 打赏
  • 举报
回复
gz
bluesx 2003-07-23
  • 打赏
  • 举报
回复
不错
bluesx 2003-07-23
  • 打赏
  • 举报
回复
不错
gwycsdn 2003-07-23
  • 打赏
  • 举报
回复
楼主真是好人,向你学习!向你致敬!
cenxaoi 2003-07-23
  • 打赏
  • 举报
回复
public class MSSqlDbType
{
string _Max="";
string _Min="";
public string Max
{
get
{
MaxAndMin();
if(""==_Max)
throw new Exception("该类未完善时会返回了空字串");
else
return _Max;
}
}
public string Min
{
get
{
MaxAndMin();
if(""==_Min)
throw new Exception("该类未完善时会返回了空字串");
else
return _Min;
}
}
int _Length=1;
public int Length
{
get{return _Length; }
set
{
if(0==value)
_Length=1;
else
_Length=value;
}
}
SqlDbType _MSSqlDataType;
public SqlDbType MSSqlDataType
{
get{return _MSSqlDataType;}
set
{
if(value==SqlDbType.UniqueIdentifier||value==SqlDbType.Variant||
value==SqlDbType.Timestamp||value==SqlDbType.Text||value==SqlDbType.NText||value==SqlDbType.Image)
{
throw new Exception ("该类不支持 UniqueIdentifier,Variant,Timestamp,Text,NText,Image类型数据。");
}
else
{
_MSSqlDataType=value;
}
}
}
/// <summary>
/// 计算出某种类型的最大值的字串和最小字串
/// </summary>
void MaxAndMin()
{
string temp="";
switch(_MSSqlDataType)
{
#region 数字类型 不需要Length
case SqlDbType.BigInt:
this._Max="9223372036854775807";
this._Min="-9223372036854775808";
break;
case SqlDbType.Int:
this._Max="2147483647";
this._Min="-2147483648";
break;
case SqlDbType.SmallInt:
this._Max="32767";
this._Min="-32768";
break;
case SqlDbType.TinyInt:
this._Max="0";
this._Min="255";
break;
#endregion
#region 数字类型 需要Length 按无Length处理
case SqlDbType.Float:
case SqlDbType.Real:
case SqlDbType.Decimal:
this._Max="99999999999999999999999999999999999999";
this._Min="-99999999999999999999999999999999999999";
break;
#endregion
#region 货币
case SqlDbType.Money:
this._Max="922337203685477.5807";
this._Min="-922337203685477.5808";
break;
case SqlDbType.SmallMoney:
this._Max="214748.3647";
this._Min="-214748.3648";
break;
#endregion
#region 日期
case SqlDbType.SmallDateTime:
this._Max="'2079-6-6'";
this._Min="'1900-1-1'";
break;
case SqlDbType.DateTime:
this._Max="'9999-12-31'";
this._Min="'1753-1-1'";
break;
#endregion
#region 字符类型和binnary类型
case SqlDbType.VarChar:
temp=temp.PadLeft(this.Length*2,'f');
this._Max="convert(varchar,0x"+temp+")";
this._Min="''";
break;
case SqlDbType.Char:
temp=temp.PadLeft(this.Length*2,'f');
this._Max="convert(char,0x"+temp+")";
this._Min="''";
break;
case SqlDbType.NVarChar:
temp.PadLeft(this.Length*4,'f');
this._Max="convert(nvarchar,0x"+temp+")";
this._Min="''";
break;
case SqlDbType.NChar:
temp.PadLeft(this.Length*4,'f');
this._Max="convert(nchar,0x"+temp+")";
this._Min="''";
break;
case SqlDbType.Binary:
case SqlDbType.VarBinary:
temp.PadLeft(this.Length*2,'f');
this._Max="0x"+temp;
this._Max="0x00";
break;
#endregion
#region 其它
case SqlDbType.Bit:
this._Max="1";
this._Min="0";
break;
#endregion
}
}



void StringToType(string DataType)
{
switch(DataType)
{
case "bigint":
this._MSSqlDataType=SqlDbType.BigInt;
break;
case "int":
this._MSSqlDataType=SqlDbType.Int;
break;
case "smallint":
this._MSSqlDataType=SqlDbType.SmallInt;
break;
case "tinyint":
this._MSSqlDataType=SqlDbType.TinyInt;
break;
case "float":
this._MSSqlDataType=SqlDbType.Float;
break;
case "real":
this._MSSqlDataType=SqlDbType.Real;
break;
case "decimal":
this._MSSqlDataType=SqlDbType.Decimal;
break;
case "money":
this._MSSqlDataType=SqlDbType.Money;
break;
case "smallmoney":
this._MSSqlDataType=SqlDbType.SmallMoney;
break;
case "smalldatetime":
this._MSSqlDataType=SqlDbType.SmallDateTime;
break;
case "datetime":
this._MSSqlDataType=SqlDbType.DateTime;
break;
case "varchar":
this._MSSqlDataType=SqlDbType.VarChar;
break;
case "char":
this._MSSqlDataType=SqlDbType.Char;
break;
case "nvarchar":
this._MSSqlDataType=SqlDbType.NVarChar;
break;
case "nchar":
this._MSSqlDataType=SqlDbType.NChar;
break;
case "binary":
this._MSSqlDataType=SqlDbType.Binary;
break;
case "varbinary":
this._MSSqlDataType=SqlDbType.VarBinary;
break;
default:
throw new Exception("该类不支持"+DataType+"类型.");

}
}
public MSSqlDbType()
{}
public MSSqlDbType(SqlDbType DataType)
{ this.MSSqlDataType=DataType; }
public MSSqlDbType(SqlDbType DataType,int Length)
{ this.MSSqlDataType=DataType; this.Length=Length; }
public MSSqlDbType(string DataType,int Length)
{
StringToType(DataType.ToLower());
this.Length=Length;
}
public MSSqlDbType(string DataType)
{
StringToType(DataType.ToLower());
}
}


调用的代码:
SqlPagination b=new SqlPagination("表或视图","KeyField字段,用于排序的字段","使用MSSqlDbType类,表示KeyField字段的属性");
SqlPagination b=new SqlPagination("Table","id",new MSSqlDbType(System.Data.SqlDbType.Int)); //或
SqlPagination b=new SqlPagination("Table","name",new MSSqlDbType(System.Data.SqlDbType.VarChar,20));
b.CurrentPage=20; //当前页,页号从1开始
b.PageSize=20; //页大小
b.Condition="name like '陈%' and age > 20"; //条件
b.Desc=true; //KeyField字段按升序查还是按降序
b.OrderField="name,age"; //其它排序字段
b.Fields="*"; //返回字段
string Select=b.Select(); //返回查询语句


该类只是简单的类,主要是配置查询语句,功能不完善。请各位自己扩展。如果乐意的话请把你扩展后的代码发到cenxaoi@163.com,交流交流。
最后多谢各位捧场。
lqf802 2003-07-23
  • 打赏
  • 举报
回复
你真是太好心了.......
相关推荐
发帖
.NET社区

6.1w+

社区成员

.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
帖子事件
创建了帖子
2003-07-23 11:16
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。