天天看點

分頁查詢算法實踐

馬上要畢業了,心裡很迷茫,感覺真的時間飛逝,軟體真的博大精深,特别.net平台在microsoft下變化之迅猛,個人總是趕不上技術的日新月異。哎,希望自己能早日走上設計之路。

閑來無事便根據自己大學四年項目實踐經驗,想實作一些常用子產品的抽象和內建。考慮了一下覺得先該從分頁查詢入手,便簡單的設計了下,現目前版本實作了單表的基本分頁查詢。我知道部落格園了已經有很多前輩做了這個,本人設計能力和前輩們比那就欠缺多了,有那裡不足的望指出,大家共同進步。

主要采用工廠模式建立實作了pagesqlbase的對象,然後可以利用對象的getsql()方法傳回查詢sql語句。我的目的是生成sql語句并非直接從資料庫取得資料,因為我認為如果這樣将會增加耦合度增加,不易于移植通用,也不與分頁控件結合,于是為了降低耦合度,我認為分頁控件的職責是ui的顯示而并非分頁算法等的處理,更非資料的讀取。

1.vs類圖為:

分頁查詢算法實踐

2其中pagesqlbase抽象類為:

分頁查詢算法實踐
分頁查詢算法實踐

代碼

 1 namespace wolf.pager

 2 {

 3     public abstract class pagesqlbase

 4 {

 5 //查詢資訊

 6         public searchinfo searchinfo

 7         {

 8             get;

 9             set;

10         }

11 //page資訊

12         public pageinfo pageinfo

13         {

14             get;

15             set;

16         }

17         public abstract string getsql();

18     }

19 }

20 

分頁查詢算法實踐

3 我在類庫實作了多種分頁算法,網上到處都有算法的描述,在這裡我就不講解了。隻展示一下針對sqlserver低版本(2000)的分頁算法選擇類,因他的算法用top并且不同的算法針對不同的主鍵和排序形式,為了效率的優化故應該選擇不同的算法。它采用的擴充卡的方式實作的。

分頁查詢算法實踐
分頁查詢算法實踐

 1 using system;

 2 using system.collections.generic;

 3 using system.linq;

 4 using system.text;

 5 

 6 namespace wolf.pager

 7 {

 8     public class sqlserverlowerlevelpagesql:pagesqlbase

 9     {

10         public override string getsql()

11         {

12             if (pageinfo == null || searchinfo == null)

13             {

14                 throw new argumentnullexception("page資訊和search資訊不能為空!");

15             }

16             return pagesqlchoise().getsql();

17         }

18 

19         protected virtual pagesqlbase pagesqlchoise()

20         {

21             if (searchinfo.uniquefieldcollection != null)

22             {

23                 if (searchinfo.uniquefieldcollection.count == 1)

24                 {

25                     if (searchinfo.orderexpress != null)

26                     {

27                         if (searchinfo.orderexpress.count == 1 && searchinfo.orderexpress[0].filed.tolower()

28                             .equals(searchinfo.uniquefieldcollection[0].name.tolower()))

29                         {//單鍵唯一排序字段

30                             return initpagesql(new topmaxpagesql());

31                         }

32                         else// 單鍵多排序

33                         {

34                             return initpagesql(new topmutilporderpagesql());

35                         }

36                     }

37                     else//單鍵無排序(預設鍵值排序)

38                     {

39                         return initpagesql(new topmaxpagesql());

40                     }

41                 }

42                 else//聯合(多)鍵

43                 {

44                     return initpagesql(new topmutilpkeypagesql());

45                 }

46             }

47             else if (searchinfo.orderexpress != null && searchinfo.orderexpress.count > 0)

48                 //無鍵(聯合建作為排序字段)//設計時把聯合建作為了排序字段

49             {

50                 return initpagesql(new topmutilpkeypagesql());

51             }

52             else

53             {

54                 throw new argumentnullexception("page資訊和search資訊不能為空!");

55             }

56 

57         }

58 

59         private pagesqlbase initpagesql(pagesqlbase psb)

60         {

61             psb.searchinfo = searchinfo;

62             psb.pageinfo = pageinfo;

63             return psb;

64         }

65     }

66 }

67 

68 

69 

分頁查詢算法實踐

4: 工廠類的實作方式代碼如下:

分頁查詢算法實踐
分頁查詢算法實踐

  1 using system;

  2 using system.collections;

  3 using system.reflection;

  4 

  5 namespace wolf.pager

  6 {

  7     public class pagefactory

  8     {        

  9         private static readonly pagefactory pagefactory = new pagefactory();

 10         private hashtable ht;

 11         private pagefactory()

 12         {

 13             ht = new hashtable();

 14         }

 15         public static pagefactory instance

 16         {

 17             get

 18             {

 19                 return pagefactory;

 20             }

 21         }

 22 

 23         /// <summary>

 24         /// 根據配置節建立分頁算法:資料庫類型的配置優秀權大于算法dll的配置;

 25         /// </summary>

 26         /// <returns></returns>

 27         public pagesqlbase create()

 28         {

 29             try

 30             {

 31                 try

 32                 {

 33 //先檢查config中是否配置了資料庫類型,優先級高些

 34                     string databasetype = system.configuration.configurationmanager.appsettings["databasetype"].tostring();

 35                     databasetype dbtype = (databasetype)enum.parse(typeof(databasetype), databasetype, true) ;

 36                     return create(dbtype);

 37                 }

 38                 catch (exception)

 39                 {

 40                 }

 41 //檢查config中是否配置了算法程式資訊

 42                 string dll = system.configuration.configurationmanager.appsettings["assembly"].tostring();

 43                 string name = system.configuration.configurationmanager.appsettings["namespace"] == null ? system.configuration.configurationmanager.appsettings["assembly"].tostring()

 44                     : dll;

 45                 string type = system.configuration.configurationmanager.appsettings["type"].tostring();

 46                 if (string.isnullorempty(dll) || string.isnullorempty(type))

 47                 {

 48                     throw new invalidoperationexception("沒有配置pagesql節");

 49                 }

 50                 return create(dll, name, type);

 51             }

 52             catch (nullreferenceexception)

 53             {

 54 

 55                 throw new invalidoperationexception("不存在相應配置pagesql節");

 56             }

 57 

 58 

 59         }

 60 

 61         public pagesqlbase create(string dll, string type)

 62         {

 63             return create(dll, dll, type);

 64         }

 65 

 66         public pagesqlbase create(string dll, string name, string type)

 67         {

 68 //緩存,減少程式集的加載

 69             string key = (dll + "$" + name + "." + type).tolower();

 70             if (ht.containskey(key) && ht[key] != null)

 71             {

 72                 type ty = ht[key].gettype();

 73                 object obj = ty.assembly.createinstance(ty.fullname, true);

 74                 return obj as pagesqlbase;

 75             }

 76             assembly asm = assembly.load(dll);

 77             type t = asm.gettype(name + "." + type, true, true);

 78             if (t.isabstract || t.isinterface || !typeof(pagesqlbase).isassignablefrom(t))

 79             {

 80                 throw new argumentexception("目前參數不合法");

 81             }

 82             pagesqlbase pagesql = asm.createinstance(name + "." + type) as pagesqlbase;

 83             ht.add(key, pagesql);

 84             return pagesql;

 85         }

 86 

 87         public pagesqlbase create(databasetype database)

 88         {

 89             switch (database)

 90             {

 91                 case databasetype.db2:

 92                     return db2arithmetic();

 93                 case databasetype.mysql:

 94                     return mysqlarithmetic();

 95                 case databasetype.oracel:

 96                     return oracelarithmetic();

 97                 case databasetype.sqlserverhightlevel:

 98                     return sqlserverhightlevelarithmetic();

 99                 case databasetype.sqlserverlowerlevel:

100                     return sqlserverlowerlevelarithmetic();

101                 default:

102                     return defaultarithmetic();

103             }

104         }

105 

106         protected virtual pagesqlbase db2arithmetic()

107         {

108             return new db2pagesql();

109         }

110 

111         protected virtual pagesqlbase mysqlarithmetic()

112         {

113             return new mysqllimitpagesql();

114         }

115 

116         protected virtual pagesqlbase oracelarithmetic()

117         {

118             return new oraclepagesql();

119         }

120 

121         protected virtual pagesqlbase sqlserverhightlevelarithmetic()

122         {

123             return new mssql2005row_numberpagesql();

124         }

125 

126         protected virtual pagesqlbase sqlserverlowerlevelarithmetic()

127         {

128             return new sqlserverlowerlevelpagesql();

129         }

130 

131         protected virtual pagesqlbase defaultarithmetic()

132         {

133             return new topmutilporderpagesql();

134         }

135     }

136 }

137 

138 

分頁查詢算法實踐

我的測試配置configu為:

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

<configuration>

 <appsettings>

    <add key="databasetype" value="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層必須與資料層相隔離。

希望能先多開發些常用子產品,減少以後的代碼量,加快開發速度。我的目标是能開發一個小型管理系統的通用開發和配置平台。