分页查询算法实践

马上要毕业了,心里很迷茫,感觉真的时间飞逝,软件真的博大精深,特别.NET平台在Microsoft下变化之迅猛,个人总是赶不上技术的日新月异。哎,希望自己能早日走上设计之路。

闲来无事便根据自己大学四年项目实践经验,想实现一些常用模块的抽象和集成。考虑了一下觉得先该从分页查询入手,便简单的设计了下,现目前版本实现了单表的基本分页查询。我知道博客园了已经有很多前辈做了这个,本人设计能力和前辈们比那就欠缺多了,有那里不足的望指出,大家共同进步。

下载代码:WolfPager下载

主要采用工厂模式创建实现了PageSqlBase的对象,然后可以利用对象的GetSql()方法返回查询Sql语句。我的目的是生成sql语句并非直接从数据库取得数据,因为我认为如果这样将会增加耦合度增加,不易于移植通用,也不与分页控件结合,于是为了降低耦合度,我认为分页控件的职责是UI的显示而并非分页算法等的处理,更非数据的读取。

1.VS类图为:分页查询算法实践

2其中PageSqlBase抽象类为:
 

  1. 代码   
  2.  1 namespace Wolf.Pager  
  3.  2 {  
  4.  3     public abstract class PageSqlBase  
  5.  4 {  
  6.  5 //查询信息  
  7.  6         public SearchInfo SearchInfo  
  8.  7         {  
  9.  8             get;  
  10.  9             set;  
  11. 10         }  
  12. 11 //Page信息  
  13. 12         public PageInfo PageInfo  
  14. 13         {  
  15. 14             get;  
  16. 15             set;  
  17. 16         }  
  18. 17         public abstract string GetSql();  
  19. 18     }  
  20. 19 }  
  21. 20  

我在类库实现了多种分页算法,网上到处都有算法的描述,在这里我就不讲解了。只展示一下针对SqlServer低版本(2000)的分页算法选择类,因他的算法用Top并且不同的算法针对不同的主键和排序形式,为了效率的优化故应该选择不同的算法。它采用的适配器的方式实现的。


  1. 代码   
  2.  1 using System;  
  3.  2 using System.Collections.Generic;  
  4.  3 using System.Linq;  
  5.  4 using System.Text;  
  6.  5   
  7.  6 namespace Wolf.Pager  
  8.  7 {  
  9.  8     public class SQLServerLowerLevelPageSql:PageSqlBase  
  10.  9     {  
  11. 10         public override string GetSql()  
  12. 11         {  
  13. 12             if (PageInfo == null || SearchInfo == null)  
  14. 13             {  
  15. 14                 throw new ArgumentNullException("Page信息和Search信息不能为空!");  
  16. 15             }  
  17. 16             return PageSqlChoise().GetSql();  
  18. 17         }  
  19. 18   
  20. 19         protected virtual PageSqlBase PageSqlChoise()  
  21. 20         {  
  22. 21             if (SearchInfo.UniqueFieldCollection != null)  
  23. 22             {  
  24. 23                 if (SearchInfo.UniqueFieldCollection.Count == 1)  
  25. 24                 {  
  26. 25                     if (SearchInfo.OrderExpress != null)  
  27. 26                     {  
  28. 27                         if (SearchInfo.OrderExpress.Count == 1 && SearchInfo.OrderExpress[0].Filed.ToLower()  
  29. 28                             .Equals(SearchInfo.UniqueFieldCollection[0].Name.ToLower()))  
  30. 29                         {//单键唯一排序字段  
  31. 30                             return InitPageSql(new TOPMAXPageSql());  
  32. 31                         }  
  33. 32                         else// 单键多排序  
  34. 33                         {  
  35. 34                             return InitPageSql(new TOPMutilpOrderPageSql());  
  36. 35                         }  
  37. 36                     }  
  38. 37                     else//单键无排序(默认键值排序)  
  39. 38                     {  
  40. 39                         return InitPageSql(new TOPMAXPageSql());  
  41. 40                     }  
  42. 41                 }  
  43. 42                 else//联合(多)键  
  44. 43                 {  
  45. 44                     return InitPageSql(new TopMutilpKeyPageSql());  
  46. 45                 }  
  47. 46             }  
  48. 47             else if (SearchInfo.OrderExpress != null && SearchInfo.OrderExpress.Count > 0)  
  49. 48                 //无键(联合建作为排序字段)//设计时把联合建作为了排序字段  
  50. 49             {  
  51. 50                 return InitPageSql(new TopMutilpKeyPageSql());  
  52. 51             }  
  53. 52             else 
  54. 53             {  
  55. 54                 throw new ArgumentNullException("Page信息和Search信息不能为空!");  
  56. 55             }  
  57. 56   
  58. 57         }  
  59. 58   
  60. 59         private PageSqlBase InitPageSql(PageSqlBase psb)  
  61. 60         {  
  62. 61             psb.SearchInfo = SearchInfo;  
  63. 62             psb.PageInfo = PageInfo;  
  64. 63             return psb;  
  65. 64         }  
  66. 65     }  
  67. 66 }  
  68. 67   
  69. 68   
  70. 69   
  71.    
  72.  

4


  1. 代码   
  2.   1 using System;  
  3.   2 using System.Collections;  
  4.   3 using System.Reflection;  
  5.   4   
  6.   5 namespace Wolf.Pager  
  7.   6 {  
  8.   7     public class PageFactory  
  9.   8     {          
  10.   9         private static readonly PageFactory pageFactory = new PageFactory();  
  11.  10         private Hashtable ht;  
  12.  11         private PageFactory()  
  13.  12         {  
  14.  13             ht = new Hashtable();  
  15.  14         }  
  16.  15         public static PageFactory Instance  
  17.  16         {  
  18.  17             get  
  19.  18             {  
  20.  19                 return pageFactory;  
  21.  20             }  
  22.  21         }  
  23.  22   
  24.  23         /// <summary>  
  25.  24         /// 根据配置节创建分页算法:数据库类型的配置优秀权大于算法Dll的配置;  
  26.  25         /// </summary>  
  27.  26         /// <returns></returns>  
  28.  27         public PageSqlBase Create()  
  29.  28         {  
  30.  29             try  
  31.  30             {  
  32.  31                 try  
  33.  32                 {  
  34.  33 //先检查Config中是否配置了数据库类型,优先级高些  
  35.  34                     string DataBaseType = System.Configuration.ConfigurationManager.AppSettings["DataBaseType"].ToString();  
  36.  35                     DataBaseType dbtype = (DataBaseType)Enum.Parse(typeof(DataBaseType), DataBaseType, true) ;  
  37.  36                     return Create(dbtype);  
  38.  37                 }  
  39.  38                 catch (Exception)  
  40.  39                 {  
  41.  40                 }  
  42.  41 //检查Config中是否配置了算法程序信息  
  43.  42                 string dll = System.Configuration.ConfigurationManager.AppSettings["Assembly"].ToString();  
  44.  43                 string name = System.Configuration.ConfigurationManager.AppSettings["NameSpace"] == null ? System.Configuration.ConfigurationManager.AppSettings["Assembly"].ToString()  
  45.  44                     : dll;  
  46.  45                 string type = System.Configuration.ConfigurationManager.AppSettings["Type"].ToString();  
  47.  46                 if (string.IsNullOrEmpty(dll) || string.IsNullOrEmpty(type))  
  48.  47                 {  
  49.  48                     throw new InvalidOperationException("没有配置PageSql节");  
  50.  49                 }  
  51.  50                 return Create(dll, name, type);  
  52.  51             }  
  53.  52             catch (NullReferenceException)  
  54.  53             {  
  55.  54   
  56.  55                 throw new InvalidOperationException("不存在相应配置PageSql节");  
  57.  56             }  
  58.  57   
  59.  58   
  60.  59         }  
  61.  60   
  62.  61         public PageSqlBase Create(string dll, string type)  
  63.  62         {  
  64.  63             return Create(dll, dll, type);  
  65.  64         }  
  66.  65   
  67.  66         public PageSqlBase Create(string dll, string name, string type)  
  68.  67         {  
  69.  68 //缓存,减少程序集的加载  
  70.  69             string key = (dll + "$" + name + "." + type).ToLower();  
  71.  70             if (ht.ContainsKey(key) && ht[key] != null)  
  72.  71             {  
  73.  72                 Type ty = ht[key].GetType();  
  74.  73                 object obj = ty.Assembly.CreateInstance(ty.FullName, true);  
  75.  74                 return obj as PageSqlBase;  
  76.  75             }  
  77.  76             Assembly asm = Assembly.Load(dll);  
  78.  77             Type t = asm.GetType(name + "." + type, truetrue);  
  79.  78             if (t.IsAbstract || t.IsInterface || !typeof(PageSqlBase).IsAssignableFrom(t))  
  80.  79             {  
  81.  80                 throw new ArgumentException("当前参数不合法");  
  82.  81             }  
  83.  82             PageSqlBase pageSql = asm.CreateInstance(name + "." + type) as PageSqlBase;  
  84.  83             ht.Add(key, pageSql);  
  85.  84             return pageSql;  
  86.  85         }  
  87.  86   
  88.  87         public PageSqlBase Create(DataBaseType dataBase)  
  89.  88         {  
  90.  89             switch (dataBase)  
  91.  90             {  
  92.  91                 case DataBaseType.DB2:  
  93.  92                     return DB2Arithmetic();  
  94.  93                 case DataBaseType.MySQL:  
  95.  94                     return MySqlArithmetic();  
  96.  95                 case DataBaseType.Oracel:  
  97.  96                     return OracelArithmetic();  
  98.  97                 case DataBaseType.SQLServerHightLevel:  
  99.  98                     return SQLServerHightLevelArithmetic();  
  100.  99                 case DataBaseType.SQLServerLowerLevel:  
  101. 100                     return SQLServerLowerLevelArithmetic();  
  102. 101                 default:  
  103. 102                     return DefaultArithmetic();  
  104. 103             }  
  105. 104         }  
  106. 105   
  107. 106         protected virtual PageSqlBase DB2Arithmetic()  
  108. 107         {  
  109. 108             return new DB2PageSql();  
  110. 109         }  
  111. 110   
  112. 111         protected virtual PageSqlBase MySqlArithmetic()  
  113. 112         {  
  114. 113             return new MySqlLimitPageSql();  
  115. 114         }  
  116. 115   
  117. 116         protected virtual PageSqlBase OracelArithmetic()  
  118. 117         {  
  119. 118             return new OraclePageSql();  
  120. 119         }  
  121. 120   
  122. 121         protected virtual PageSqlBase SQLServerHightLevelArithmetic()  
  123. 122         {  
  124. 123             return new MSSQL2005Row_NumberPageSql();  
  125. 124         }  
  126. 125   
  127. 126         protected virtual PageSqlBase SQLServerLowerLevelArithmetic()  
  128. 127         {  
  129. 128             return new SQLServerLowerLevelPageSql();  
  130. 129         }  
  131. 130   
  132. 131         protected virtual PageSqlBase DefaultArithmetic()  
  133. 132         {  
  134. 133             return new TOPMutilpOrderPageSql();  
  135. 134         }  
  136. 135     }  
  137. 136 }  
  138. 137   

 

我的测试配置Configu为:

<?xml version="1.0encoding="utf-8" ?>

<configuration>

 <appSettings>

    <add key="DataBaseTypevalue="SQLServerLowerLevel"/>

    <!--<add key="Assembly" value="ConsoleTest"/>

    <add key="NameSpace" value="ConsoleTest"/>

    <add key="Type" value="Program"/>-->

 </appSettings>

</configuration>

测试结果性能比较高效,具体大家把代码下载看。

 本版本只是一个初步的实践摸索版本,离使用还应该差一些,我会有时间在改进,主要应该还要加入:

1:多表查询的分页方式。

2:GroupBy分组统计方式的分页查询。

3:添加是内存数据统计的类库。

4:缓存机制的加入(初步打算用OS的页面置换算法LRU(最近最少使用),加入超时减少缓存带来的数据不一致性)。

  分页控件的设计暂时没考虑太多,我认为Web控件应该可以支持URl、PoatBack、Ajax三种方式,具体实现可以用简单工厂。Winform的当然就一种方式了。数据库处理应该有程序员了事件代码中挂载。UI和BL层必须与数据层相隔离。

 

希望能先多开发些常用模块,减少以后的代码量,加快开发速度。我的目标是能开发一个小型管理系统的通用开发和配置平台

: 工厂类的实现方式代码如下:

 

 




 本文转自 破狼 51CTO博客,原文链接:http://blog.51cto.com/whitewolfblog/834142,如需转载请自行联系原作者


上一篇:Greenplum 空间(GIS)数据检索 B-Tree & GiST 索引实践 - 阿里云HybridDB for PostgreSQL最佳实践


下一篇:找到某个技术点答案的正确姿势以const和ref_eq区别为例