只是一個用EF寫的一個簡單的分頁方法而已
慢慢的寫吧。比如,第一步,先把所有數據查詢出來吧。

1 //第一步。 2 public IQueryable<UserInfo> LoadPagesForUserInfos(int pageSize, int pageIndex, out int total) 3 { 4 DataModelContainer db = new DataModelContainer(); 5 total = db.UserInfo.Count(); 6 return db.UserInfo.Take(pageSize*(pageIndex - 1)).Skip(pageSize).AsQueryable(); 7 }
第二步。我總不能全查詢出來吧,我得有些條件吧。比如我要查id>18的數據。那么得用到Where()擴展方法了。那么就得這么寫了。

1 public IQueryable<UserInfo> LoadPagesInfos(int pageSize, int pageIndex, out int total) 2 { 3 DataModelContainer db = new DataModelContainer(); 4 total = db.UserInfo.Where(u => u.ID > 18).Count(); 5 return db.UserInfo.Where(u => u.ID > 18).Take(pageSize * (pageIndex - 1)).Take(pageSize).AsQueryable(); 6 }
第三步,我查詢數據的條件,可能會變,比如我現在不查id>18的數據了,我要查id<100的數據或者公司名字叫“小杜的公司”的數據,你總不能老在這里給我改代碼吧。那么我們發現,其擴展方法就是傳一個委托,一個名傳入是UserInfo類型返回值是bool類型的委托,那么我們把這個委托當參數傳遞過來,讓用戶傳就好了。需要什么用戶寫好傳遞過來也就可以了。就很好的做到了對變化點的封裝。

1 public IQueryable<UserInfo> LoadPagesForInfos(int pageSize, int pageIndex, out int total, Func<UserInfo, bool> whereFunc) 2 { 3 DataModelContainer db = new DataModelContainer(); 4 total = db.UserInfo.Where(whereFunc).Count(); 5 return db.UserInfo.Where(whereFunc).Skip(pageSize * (pageIndex - 1)).Take(pageSize).AsQueryable(); 6 }
第四步,查詢條件現在是可以用戶傳遞的了,可是分頁查詢總得有一個排序吧。這樣就需要用到Order()方法了。下面代碼中的Order<UserInfo,int>(u=>u.ID)中接口是約束了這個UserInfo,而后面的int則是約束后面Lambda的返回值的。我們轉到定義就可以發現了。當然這個“<>”里的內容也是可以不寫的,此處如不寫的話是后面的Lambda表示式亦會自動推測出前面的限制是什么的。如同Skip()方法和Take()方法就沒有寫。那么,優化一下,寫一個按id排序的方法吧。

1 public IQueryable<UserInfo> LoadPagesForInfos(int pageSize, int pageIndex, out int total, 2 Func<UserInfo, bool> whereFunc) 3 { 4 DataModelContainer db = new DataModelContainer(); 5 total = db.UserInfo.Where(whereFunc).Count(); 6 return 7 db.UserInfo.Where(whereFunc) 8 .OrderBy<UserInfo, int>(u => u.ID) 9 .Skip(pageSize * (pageIndex - 1)) 10 .Take(pageSize) 11 .AsQueryable(); 12 }
第五步,暫且就只傳遞int類型的,可是我一會是想按id>18的排序,一會是想按編號小於100的來排序,總不能按個要求就跑到這里來改代碼吧。那么這是一個變化點,可不可以封裝一下呢,讓用戶來傳遞呢,自然是可以的,依舊同上,OrderBy需要的是一個傳入的是UserInfo類型,傳出的是一個bool類型一個委托。我們將其提取出來,讓其在方法參數那里傳遞過來就可以了。

1 public IQueryable<UserInfo> LoadPagesForInfos(int pageSize, int pageIndex, out int total, 2 Func<UserInfo, bool> whereFunc,Func<UserInfo,int> orderByFunc ) 3 { 4 DataModelContainer db = new DataModelContainer(); 5 total = db.UserInfo.Where(whereFunc).Count(); 6 return 7 db.UserInfo.Where(whereFunc) 8 .OrderBy<UserInfo, int>(orderByFunc)//"<>"號是可以去掉的。這里同上面是不一樣的。 9 .Skip(pageSize * (pageIndex - 1)) 10 .Take(pageSize) 11 .AsQueryable(); 12 }
第六步,傳遞的值的話可能是int類型,也有可能是其他的類型,讓用戶一直傳int類型的不太合適吧。可不可以,讓用戶隨便傳遞什么類型呢。比如時間(DateTime類型)來排序,自然可以,這樣就需要用到泛型。泛型此處就不用類泛型,用方法泛型,使其職責單一,上面約束的是什么類型,下面就是什么類型。當我們對其約束之后,就是我們需要一個傳入類型是UserInfo,傳出的類型是T類型的一個委托了。依舊如上面的,我們將此委托當一個參數傳遞也就好了。就很好的做到了對此變化點的封裝了。跟第五步對比,也就是將加了一個方法泛型和OrderBy()方法對返回值的約束改成了"T"就可以了。用戶想按id來排序就傳id相應的Lambda,想按DateTime來排序就傳相應的Lambda就可以了。

1 public IQueryable<UserInfo> LoadPagesForInfos<T>(int pageSize, int pageIndex, out int total, 2 Func<UserInfo, bool> whereFunc, Func<UserInfo, T> orderByFunc) 3 { 4 DataModelContainer db = new DataModelContainer(); 5 total = db.UserInfo.Where(whereFunc).Count(); 6 return 7 db.UserInfo.Where(whereFunc) 8 .OrderBy<UserInfo, T>(orderByFunc) 9 .Skip(pageSize * (pageIndex - 1)) 10 .Take(pageIndex) 11 .AsQueryable(); 12 }
第七步,升序還是降序,排列。加個bool類型的isAsc的參數吧。小判斷一下。

1 public IQueryable<UserInfo> LoadPagesForInfos<T>(int pageSize, int pageIndex, out int total, 2 Func<UserInfo, bool> whereFunc, Func<UserInfo, T> orderByFunc,bool isAsc) 3 { 4 DataModelContainer db = new DataModelContainer(); 5 total = db.UserInfo.Where(whereFunc).Count(); 6 if (isAsc) 7 { 8 return 9 db.UserInfo.Where(whereFunc) 10 .OrderBy<UserInfo, T>(orderByFunc) 11 .Skip(pageSize * (pageIndex - 1)) 12 .Take(pageIndex) 13 .AsQueryable(); 14 } 15 else 16 { 17 return 18 db.UserInfo.Where(whereFunc) 19 .OrderByDescending<UserInfo, T>(orderByFunc) 20 .Skip(pageSize * (pageIndex - 1)) 21 .Take(pageIndex) 22 .AsQueryable(); 23 } 24 }
貌似就這樣這個方法還不錯的樣子,附上一下完整方法的圖片,喜歡這個字體,我將EF上下文的對象提到了最上面。
求指教,共同進步。