基类
/// <summary>
/// 执行SQL查询,返回分页记录集
/// </summary>
/// <param name="sql">SQL语句</param>
/// <param name="startRowIndex">开始行,1开始</param>
/// <param name="maximumRows">最大返回行数</param>
/// <param name="keyColumn">主键列。用于not in分页</param>
/// <returns></returns>
public virtual DataSet Query(String sql, Int32 startRowIndex, Int32 maximumRows, String keyColumn)
{
// 从第一行开始,不需要分页
if (startRowIndex <= 1)
{
if (maximumRows < 1)
return Query(sql);
else
return Query(String.Format("Select Top {0} * From ({1}) a", maximumRows, sql));
}
if (maximumRows < 1)
sql = String.Format("Select * From ({1}) b Where {2} Not In(Select Top {0} {2} From ({1}) a)", startRowIndex - 1, sql, keyColumn);
else
sql = String.Format("Select Top {0} * From ({1}) b Where {2} Not In(Select Top {3} {2} From ({1}) a)", startRowIndex + maximumRows - 1, sql, keyColumn, startRowIndex - 1);
return Query(sql);
}派生类
public override DataSet Query(string sql, int startRowIndex, int maximumRows, string keyColumn)
{
// 如果没有Order By,直接调用基类方法
// 先用字符串判断,如果命中率高,这样可以提高处理效率
if (!sql.Contains("order")) return base.Query(sql, startRowIndex, maximumRows, keyColumn);
if (!sql.ToLower().Contains("order")) return base.Query(sql, startRowIndex, maximumRows, keyColumn);
// 使用正则进行严格判断。必须包含Order By,并且它右边没有右括号),表明有order by,且不是子查询的,才需要特殊处理
MatchCollection ms = Regex.Matches(sql, @"\border\s*by\b[^)]+$", RegexOptions.Compiled | RegexOptions.IgnoreCase);
if (ms == null || ms.Count < 1 || ms[0].Index < 1)
{
return base.Query(sql, startRowIndex, maximumRows, keyColumn);
}
// 已确定该sql最外层含有order by,再检查最外层是否有top。因为没有top的order by是不允许作为子查询的
if (!Regex.IsMatch(sql, @"^[^(]+\btop\b", RegexOptions.Compiled | RegexOptions.IgnoreCase))
{
return base.Query(sql, startRowIndex, maximumRows, keyColumn);
}
String orderBy = sql.Substring(ms[0].Index);
sql = sql.Substring(0, ms[0].Index); // 从第一行开始,不需要分页
if (startRowIndex <= 1)
{
if (maximumRows < 1)
return Query(sql);
else
return Query(String.Format("Select Top {0} * From ({1}) a {2}", maximumRows, sql, orderBy));
}
if (maximumRows < 1)
sql = String.Format("Select * From ({1}) b Where {2} Not In(Select Top {0} {2} From ({1}) a {3}) {3}", startRowIndex - 1, sql, keyColumn, orderBy);
else
sql = String.Format("Select Top {0} * From ({1}) b Where {2} Not In(Select Top {3} {2} From ({1}) a {4}) {4}", startRowIndex + maximumRows - 1, sql, keyColumn, startRowIndex - 1, orderBy);
return Query(sql);
}Access的DAL继承基类的时候,是不需要重写这个方法的,现在SqlServer就要做一个特殊处理,所以需要重启。感谢大家!~^_^

解决方案 »

  1.   

    我是继承DataGrid 封装了分页排序功能 
    做个控件
      

  2.   

    我的代码,在750万数据下测试通过。@ ombpk
    哪里偏低?说说看。这是最流行的sqlserver的not in分页方法@sunzhong2003
    那是页面层的控件吧,我这里可是做在数据层的。@xinfan
    呵呵,这样分页,就得取出所有数据了。不行你试试看,一千万数据。@zjx_sir
    意义就是:调用数据层获取数据的时候,只需要写一个sql,然后指定要获取的数据的范围,就可以得到这个范围的数据,而调用者不需要懂得数据分页的写法,也屏蔽了数据库的差异,根据不同的数据库使用不用的分页算法。
      

  3.   

    我个人也喜欢用这种分页方法,但是公司非要统一用aspnetpager。没办法
      

  4.   

    厄~仔细看了一下,都是SELECT,像我那样很多SELECT联合查询出来的数据集怎么分捏。
      

  5.   

    Not In这种分页随数据量的增加,速度下降的很厉害,以前用过,后来不用,其实还有一种更快的
      

  6.   

    ◎aliketen 更快的是数字主键的双反向分页,我这里也支持了^_^http://bbs.nnhy.orgX框架
      

  7.   

    最流行的sqlserver的not   in分页方法
    =================================================
    呵呵,其实没有什么最流行,又不是什么新技术
    个人喜欢就行了