Entity Framework分页在我初入门时总是困扰这我,无论是SQL分页还是Entity Framework的分页,总是显得那么麻烦,因此对于Entity Framework单独封装了分页。
一、分页原理
对于分页本质是针对现有数据进行分段展示,如图:
对于这12条数据属于筛选后的数据,针对筛选后的数据我们再进行分页,PageSize(每页数量),最后一页数量>0 && <PageSize则算一页。
二、分页设计(对于设计并不是很专业,马马虎虎)
最终我们通过PageListBase作为实现类,在通过扩展方法ExtensionIQueryable这个一个扩展类,针对IQueryable<T>进行扩展。
1 using System; 2 using System.Collections.Generic; 3 using System.Diagnostics; 4 using System.IO; 5 using System.Linq; 6 using System.Linq.Expressions; 7 using System.Runtime.Serialization; 8 using System.Runtime.Serialization.Formatters.Binary; 9 using System.Text; 10 using System.Threading.Tasks; 11 12 namespace Sunc.Framework.Repository.Entity.Extension 13 { 14 public static class ExtensionIQueryable 15 { 16 /// <summary> 17 /// 分页 18 /// </summary> 19 /// <param name="list"> 数据源 </param> 20 /// <param name="order"> 排序表达式 </param> 21 /// <param name="pageIndex"> 第几页 </param> 22 /// <param name="pageSize"> 每页记录数 </param> 23 /// <param name="count"> 记录总数 </param> 24 /// <returns></returns> 25 public static IQueryable<T> Pagination<T, TKey>(this IQueryable<T> list, Expression<Func<T, bool>> predicate, Expression<Func<T, TKey>> order, int pageIndex, int pageSize, out int count, bool isOrder = true) 26 { 27 try 28 { 29 var source = list.Where(predicate.Compile()).AsQueryable(); 30 count = source.Count(); 31 if (isOrder) 32 return source.OrderBy(order).Skip((pageIndex - 1) * pageSize).Take(pageSize); 33 return source.OrderByDescending(order).Skip((pageIndex - 1) * pageSize).Take(pageSize); 34 } 35 catch (Exception ex) 36 { 37 Console.WriteLine(ex.Message); 38 Debug.WriteLine(ex.Message); 39 count = 0; 40 return new List<T>().AsQueryable(); 41 } 42 } 43 44 public static V ToModel<T, V>(this T t) where T : ModelBase, V where V : ModelBase 45 { 46 return t; 47 } 48 public static string ToJson(this IQueryable<DatabaseModel> models) 49 { 50 return EntityBase.ToJson(models); 51 } 52 53 } 54 }
三、最终实现
1、我们使用Entity Framework应该知道懒加载
public virtual DbSet<T_WindFarm> T_WindFarm { set; get; }
我们在进行EF一系列表达式操作查询,数据实际并未查询,只用我们真正使用的时候才会执行查询。
2、EF查询
ItsmContext 扩展自 DbContext,多线程操作会存在诸多问题,因此我们采用单例模式
1 private static object _asynContextLock = new object(); 2 private static ItsmContext _context; 3 public static ItsmContext Context 4 { 5 get 6 { 7 lock (_asynContextLock) 8 { 9 if (_context == null) 10 { 11 _context = new ItsmContext(); 12 } 13 return _context; 14 } 15 } 16 }
3、实现类继承IBaseMethodPageList<Entity>
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Linq.Expressions; 5 using System.Text; 6 using System.Threading.Tasks; 7 using Sunc.Framework.Repository.Entity; 8 9 namespace Sunc.Framework.Repository.Interface.BaseMethod 10 { 11 public interface IBaseMethodPageList<Entity> 12 { 13 IBaseEntityPageList<Entity> GetPageList(int pageIndex, int pageSize); 14 15 16 IBaseEntityPageList<Entity> GetPageList<TKey>(Expression<Func<Entity, bool>> predicate, Expression<Func<Entity, TKey>> order, int pageIndex, int pageSize, bool isOrder = true); 17 } 18 }
实现类中实现方法
a、using Sunc.Framework.Repository.Entity.Extension;是针对ExtensionIQueryable的引用;
b、ItsmContext.Context.T_WindFarm.Pagination(predicate, order, pageIndex, pageSize, out count, true);我们通过筛选条件获取PageIndex即为当前页面IQueryable<T>实际结果集;
c、 var pageList = new PageListBase<T_WindFarm>(models,pageIndex,pageSize,count);我们不用在关心如何去分页,只需要把结果集和总数传入即可;
d、返回值为IBaseEntityPageList<T_WindFarm> 我们知道它继承于IBasePageList以及它的属性都为只读属性,因此我们可以防止数据被篡改。
4、最终结果
这样一来,我们不用考虑太多的分页问题
A、ExtensionIQueryable -> Pagination方法帮助我们完成数据筛选得到实际的数据总数并将实际当前页数据、总数返回;
B、PageListBase<T> 可以通过构造函数或者AddRange方法将当前页数据集加载,通过传入的count计算出实际页数。
具体的源码
IBasePageList | Sunc.Framework.Repository.Interface |
IBaseEntityPageList<Entity> | Sunc.Framework.Repository.Interface.BaseMethod |
PageListBase<Entity> | Sunc.Framework.Repository.Entity |
ExtensionIQueryable | Sunc.Framework.Repository.Entity.Extension |
IBaseMethodPageList<Entity> | Sunc.Framework.Repository.Interface.BaseMethod |
--分享源于热爱
Sunc