本文转自:http://diaosbook.com/Post/2012/9/21/linq-paging-in-entity-framework

我们知道,内存分页效率很低。并且,如果是WebForm的项目,页面上会有巨型ViewState,这必然不好。我自己博客用的是一个存储过程做的分页,用到现在都挺好,没有任何效率问题。后来想到,既然项目里有Entity Framework,那为什么不利用EF完成分页呢~

稍做研究之后发现,EF分页其实很简单。不过一样写文章了,光贴代码是不负责的,还是得稍微介绍一下相关的知识。

一、页数计算

关于分页的基本原理,网上有很多文章,我就不多叙述了。但我发现很多介绍分页的文章里,计算页码公式都掐掉了,广为流传的版本是:

totalPage = totalRecord / pageSize +
稍微推敲一下就会发现,这个公式在totalRecord和pageSize正好整除时,会多一页。比如10条记录,每页5条,应该是2页的,但结果是3。然而,不写+1又不行,因为要考虑到记录总数小于页尺寸的情况。现在,许多网站的分页都有这个问题。而我自己用的是下面这个公式,无论如何都不会掐掉的:
totalPage =(totalRecord + pageSize -)/ pageSize
注意,C#里的“/”是整除。所以这两个公式不是数学意义上的计算公式,呵呵。

二、分页存储过程的原理

(题外话:SQL Server 2012有了新的分页语法,本文只针对SQL Server 2008 R2及以往的版本)

任何分页存储过程的核心语句最后都会拼接为类似下面的这种SQL语句:

SELECT TOP(10)-- pageSize
*
FROM (
SELECT *,
ROW_NUMBER() OVER(ORDER BY [Temp].[PubDate] DESC) AS
[row_number]
FROM [dbo].[Post] AS [Temp]) AS [Temp]
WHERE [Temp].[row_number]>10--(pageIndex -1)* pageSize
ORDER BY
[Temp].[PubDate] DESC
这段SQL获取的是Post表,按PubDate逆序排列后,第二页的数据。

ROW_NUMBER()函数的作用是给查询结果生成行号,这是为了给后面的where语句用的。这个函数的具体介绍请看MSDN:http://msdn.microsoft.com/en-us/library/ms186734.aspx

三、LINQ to SQL分页

我们的目标很明确,就是最终要将LINQ语句翻译到与上面相符的SQL语句。在LINQ to SQL中,Enumerable.Take<TSource>最终会翻译为TOP(n),而Enumerable.Skip<TSource>和Take结合起来使用,就会翻译成ROW_NUMBER()…OVER…的语句。

所以,上面贴出的SQL代码的等价LINQ是:

Enumerable.OrderByDescending(p => p.PubDate).Skip().Take();
 

四、在Entity Framework中对某表分页

用EF对某表做完映射后,我们可以封装一个分页方法,比如:

private static List<Post> GetPostList(int pageIndex, int pageSize)
{
int startRow = (pageIndex - ) * pageSize;
using (var db = new EdiBlogEntities())
{
var query = db.Post.OrderByDescending(p => p.PubDate).Skip(startRow).Take(pageSize);
return query.ToList();
}
}
对于方法的返回类型,我选择List是因为调用它的程序不需要访问导航属性。如果程序中有访问导航属性的需要,就不能关闭当前的database context,应该要返回IEnumerable<T>类型。

测试代码:

static void Main(string[] args)
{
int pageIndex = ;
int pageSize = ;
int totalPage = (GetPostCount() + pageSize - ) / pageSize; Console.WriteLine("List of Posts. Page {0} / {1}, showing {2} rows per page.", pageIndex, totalPage, pageSize);
Console.WriteLine("---------------------------------------------------------");
foreach (var item in GetPostList(pageIndex, pageSize))
{
Console.WriteLine("{0}, {1}", item.Title, item.PubDate);
}
} private static int GetPostCount()
{
using (var db = new EdiBlogEntities())
{
return db.Post.Count();
}
}
 

运行结果:

和之前的存储过程分页是一致的:

[转]在Entity Framework中使用LINQ语句分页的更多相关文章

  1. 在Entity Framework 中执行T-sql语句

    从Entity Framework  4开始在ObjectContext对象上提供了2个方法可以直接执行SQL语句:ExecuteStoreQuery<T> 和 ExecuteStoreC ...

  2. Entity Framework中执行Sql语句

           如果想在EF框架中执行Sql语句,其实很简单,EF里面已经提供了相关的方法(此处使用的EF为EF4.1版本).        EF中提供了两个方法,一个是执行查询的Sql语句SqlQue ...

  3. 在Linq to sql 和 Entity framework 中使用lambda表达式实现left join

    在Linq to sql 和 Entity framework 中使用lambda表达式实现left join 我们知道lambda表达式在Linq to sql 和 Entity framework ...

  4. Entity framework 中Where、First、Count等查询函数使用时要注意

    在.Net开发中,Entity framework是微软ORM架构的最佳官方工具.我们可以使用Lambda表达式在Entity framework中DbSet<T>类上直接做查询(比如使用 ...

  5. Entity Framework中的几种加载方式

            在Entity Framework中有三种加载的方式,分别是延迟加载,自动加载和显示加载.下面用一个例子来说明:现在有两个表,一个是资料表(Reference),另外一个表是资料分类表 ...

  6. Entity Framework中DbContext结合TransactionScope提交事务的正确方式

    问: I would like know what is the best possible way to implement transactions with DBContext. In part ...

  7. Entity Framework 教程——Entity Framework中的实体类型

    Entity Framework中的实体类型 : 在之前的章节中我们介绍过从已有的数据库中创建EDM,它包含数据库中每个表所对应的实体.在EF 5.0/6.0中,存在POCO 实体和动态代理实体两种. ...

  8. 关于Entity Framework中的Attached报错相关解决方案的总结

    关于Entity Framework中的Attached报错的问题,我这里分为以下几种类型,每种类型我都给出相应的解决方案,希望能给大家带来一些的帮助,当然作为读者的您如果觉得有不同的意见或更好的方法 ...

  9. 关于Entity Framework中的Attached报错的完美解决方案终极版

    之前发表过一篇文章题为<关于Entity Framework中的Attached报错的完美解决方案>,那篇文章确实能解决单个实体在进行更新.删除时Attached的报错,注意我这里说的单个 ...

随机推荐

  1. SQL Server集群服务器的优缺点

    由二台或更多物理上独立的服务器共同组成的“虚拟”服务器称之为集群服务器.一项称做MicroSoft集群服务(MSCS)的微软服务可对集群服务器进行管理.一个SQL Server集群是由二台或更多运行S ...

  2. Java for LeetCode 031 Next Permutation

    Next Permutation Total Accepted: 33595 Total Submissions: 134095     Implement next permutation, whi ...

  3. PHP--TP框架----操作数据库

    //操作数据库                    //$attr = $m->select(); //查询所有数据                    //$attr = $m->s ...

  4. 【python】pathlib库

    pathlib在python3.2以上开始默认支持,在python2.7中如果要使用需要安装 pip install pathlib pathlib更多参考资料:http://pathlib.read ...

  5. HDU 5512 Pagodas (gcd)

    题目:传送门. 题意:t组数据,每组数据给定n,a,b,a!=b,在[1,n]的这些点中,每次选取a+b或a-b或b-a点,选取过的点在下次选取的时候可以当做ab来用继续选取,谁不能继续选取谁就输,问 ...

  6. 正则和xml解析

    一般来说是xml解析的开销比正则大些.使用正则搜索,只需搜索<second>就能定位到你要的内容,而xml解析要把节点树在内存中建立起来,所以消耗内存会多些,速度可能会受到一些影响.但对于 ...

  7. win激活查询及修改

    slmgr.vbs -dlv 命令可以查询到Win8.1的激活信息,包括:激活ID.安装ID.激活截止日期!   slmgr.vbs -dli 命令可以查询到操作系统版本.部分产品密钥.许可证状态! ...

  8. Material Design入门(三)

    本文主要包括 CollapsingToolbarLayout实现滚动动画效果 ViewPager+tabLayout实现左右类Tab效果 控件介绍 这次需要用到得新控件比较多,主要有以下几个: Coo ...

  9. 《MySQL必知必会》笔记 事务、安全及性能等

    二十六 管理事务处理 1.并非所有引擎都支持事务处理,如MyIASM和InnoDB,关于事务处理的几个术语:事务(Transaction)指一组sql语句:回退(rollback)指撤销指定SQL语句 ...

  10. Android悬浮窗注意事项

    一 动画无法运行 有时候,我们对添加的悬浮窗口,做动画的时候,始终无法运行. 那么,这个时候,我们可以对要做动画的View,再添加一个parent,即容器.将要做动画的View放入容器中. 二 悬浮窗 ...