EF Core分页查询
分页的实现
1、Skip(3).Task(8)最好显式指定排序规则
2、需要知道满足条件的数据的总条数:用IQueryable的复用LongCount和Count
3、页数:long pageCount=(long)Math.Ceiling(count*1.0/pageSize);
static void PrintPage(int pageIndex,int pageSize)
{
using MyDbContext ctx = new MyDbContext();
{
//这里先把查询规则创建出来
IQueryable<Book> books =ctx.Books.Where(b => !b.Title.Contains("张三"));
//获取满足条件的数据总条数
long count =books.LongCount();
//使用count * 1.0 / pageSize 可以计算出数据总页数,考虑到有可能最后一页不满,使用Ceiling()取整
long pageCount = (long)Math.Ceiling(count * 1.0 / pageSize);
Console.WriteLine("页数:"+pageCount);
var pagedBooks = books.Skip((pageIndex - 1) * pageSize).Take(pageSize);
foreach(var b in pageBooks)
{
Console.WriteLine(b.Id + ","+b.Title);
}
}
}
IQueryable底层是如何读取数据的?
- DataReader:分批从数据库服务器读取数据。内存占用小、DB连接占用时间长。
- DataTable:把所有数据都一次性从数据库服务器加载到客户端内存中。内存占用大,节省DB连接。
IQueryable用的是哪种?
用insert into select多插入一些数据,然后加上Delay/sleep的遍历IQueryable。在遍历执行的过程中,停止SQLServer服务器。发现报错,得出结论:IQueryable内部就是在调用DataReader
优点:节省客户端内存
缺点:如果处理的慢,会长时间占用连接
如何一次性让IQueryable加载数据到内存?
一次性加载数据到内存:用IQueryable的ToArray()、ToArrayAsync()、ToList()、ToListAsync()等方法。等ToArray()执行完毕,强制中断服务器,发现没有报错
什么时候需要一次性加载?
- 遍历IQueryable并且进行数据处理的过程中很耗时
- 如果方法需要返回查询结果,并且在方法里销毁DbCotext的话,是不能返回IQueryable的。必须一次性加载返回
- 多个IQueryable的遍历嵌套。很多数据库的ADO.NET Core Provider是不支持多个DataReader同时执行的。把连接字符串中的MultipleActiveResultSets=true删掉,其他数据数据库不支持这个语句