无心之柳

有意栽花花不开,无心插柳柳成荫
posts - 56, comments - 689, trackbacks - 2, articles - 0
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

Linq 的分页讨论

Posted on 2007-07-05 17:30 无心之柳.NET 阅读(2851) 评论(17)  编辑 收藏 所属分类: .Net

废话不数,直入主题,Linq下怎么进行分页

很多学习Linq的朋友肯定有自己所不同的方法,考虑这个问题我所想到的是

用Take(),Skip(),TakeWhile(),SkipUntil()中的方法来实现

首先看Take()是否可用

Take方法的作用是从结果中取固定数量的值,

MydbDataContext mydb=new MydbDataContext("server=.;database=mydb");

var query=from p in mydb.Products
               orderby p.id descending
               select p;//取出Products中所用的项按降序排列
如果直接用take()

var q=query.take(n) 这样只能取出前条n记录,但是还是让我们看到了分页的曙光,还是还有个skip吗,skip可以取出除去满足条件的剩下的记录。如果我们要把数据以每页pagesize的数量来进行分页,很简单,很skip(pagersize*pagenum)然后在剩下的记录中take(pagesize)不就得到了想要的数据了么。

 

varq=query.skip(pagesize*pagenum).take(pagesize) 就这么简单。

希望朋友们提供更好的方法来进行分页,同时对这个方法的优劣性,进行批评指导
附上运行时生成的SQL(感谢紫色阴影Boler Guo
sql server2000:
SELECT TOP 20 [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM (
SELECT TOP 10 [t1].[CustomerID]
FROM [dbo].[Customers] AS [t1]
) AS [t2]
WHERE [t0].[CustomerID] = [t2].[CustomerID]
))
sql server 2005
SELECT TOP 10 [t1].[CustomerID], [t1].[CompanyName], [t1].[ContactName], [t1].[ContactTitle], [t1].[Address], [t1].[City], [t1].[Region], [t1].[PostalCode], [t1].[Country], [t1].[Phone], [t1].[Fax]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ContactName]) AS [ROW_NUMBER], [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
) AS [t1]
WHERE [t1].[ROW_NUMBER] > @p0
ORDER BY [t1].[ContactName]
-- @p0: Input Int32 (Size = 0; Prec = 0; Scale = 0) [50]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.20XXX.X

Feedback

#1楼    回复  引用  查看    

2007-07-05 18:14 by Boler Guo      
楼主你可以试一试,看看生成的TSQL是什么,最好分别在SQL2000和SQL2005分别试一下。

#2楼    回复  引用  查看    

2007-07-05 18:46 by 冬冬      
@Boler Guo
支持,然后把Sql语句贴出来给大家看看。

#3楼 [楼主]   回复  引用  查看    

2007-07-05 19:08 by 无心之柳.NET      
很好的建议,但是可悲的是这里的机器上没有.net 3.5家里的才有,要周末才去家里,这台机器上不敢乱装怕搞乱现在的.net 2.0影响开发,MydbDataContext。log可以生成日志的,哪个朋友帮个忙,帮我贴一下

#4楼    回复  引用  查看    

2007-07-05 20:32 by 金色海洋(jyk)      
收藏,期待SQL语句。

#5楼    回复  引用  查看    

2007-07-05 21:06 by 紫色阴影      
sql server2000里面生成的tsql大概这样
SELECT TOP 20 [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE NOT (EXISTS(
SELECT NULL AS [EMPTY]
FROM (
SELECT TOP 10 [t1].[CustomerID]
FROM [dbo].[Customers] AS [t1]
) AS [t2]
WHERE [t0].[CustomerID] = [t2].[CustomerID]
))
在2005中不同,好像用到了rownumber。

#6楼    回复  引用    

2007-07-05 21:14 by .progame [未注册用户]
以前录过SQL dlinq生成的sql是非常高效的 MS出品 不得不服吧

#7楼    回复  引用  查看    

2007-07-05 21:22 by Boler Guo      
SQL2005:
public void LinqToSqlPaging01() {
var q = (
from c in db.Customers
orderby c.ContactName
select c)
.Skip(50)
.Take(10);

ObjectDumper.Write(q);
}
SELECT TOP 10 [t1].[CustomerID], [t1].[CompanyName], [t1].[ContactName], [t1].[ContactTitle], [t1].[Address], [t1].[City], [t1].[Region], [t1].[PostalCode], [t1].[Country], [t1].[Phone], [t1].[Fax]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ContactName]) AS [ROW_NUMBER], [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region], [t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
) AS [t1]
WHERE [t1].[ROW_NUMBER] > @p0
ORDER BY [t1].[ContactName]
-- @p0: Input Int32 (Size = 0; Prec = 0; Scale = 0) [50]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.20XXX.X

#8楼    回复  引用  查看    

2007-07-05 21:50 by dudu      
建议使用摘要方式发布。

#9楼 [楼主]   回复  引用  查看    

2007-07-05 21:55 by 无心之柳.NET      
OK,改了

#10楼    回复  引用  查看    

2007-07-06 10:27 by 随风流月      
@无心之柳.NET
不用害怕冲突问题,.Net 3.5 完全向下兼容。

#11楼    回复  引用  查看    

2007-07-06 10:51 by Anders Liu      
帅啊~~! 这都可以,看来没理由不用linq了

验证码4186

#12楼 [楼主]   回复  引用  查看    

2007-07-06 16:00 by 无心之柳.NET      
to:随风流月
怕的是不在意时,用到的3.5的功能,但是客户机上没有,呵呵

#13楼    回复  引用  查看    

2007-07-06 21:22 by 金色海洋(jyk)      
这个分页算法和那个掐头去尾的 top N 嵌套 的 也差不多呀。

#14楼    回复  引用  查看    

2007-07-07 07:35 by 随风流月      
@无心之柳.NET
只要把 System.Core 之类的类库附加上,就 OK 了。
要不然,创建项目时使用 .Net Framework 2.0

#15楼    回复  引用  查看    

2007-07-07 14:07 by 随风流月      
@金色海洋(jyk)
它是根据 Rownumber。

#16楼    回复  引用  查看    

2008-06-03 10:57 by Damon King      
to:随风流月
怕的是不在意时,用到的3.5的功能,但是客户机上没有,呵呵
开发的时候指定.net framework版本即可,这样在引用里就不会引用3.5版本的dll了,也就无法使用3.5的特性,呵呵!

#17楼    回复  引用  查看    

2008-06-03 11:04 by Damon King      
即在项目属性里将目标Frame指定版本即可!
时隔一年,估计博主已经用VS2008了,呵呵。

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2007-07-05 22:03 编辑过


相关链接: