只是一个用EF写的一个简单的分页方法而已
只是一个用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上下文的对象提到了最上面。
求指教,共同进步。