skip and take是怎么起作用的

本文关键字:起作用 and take skip | 更新日期: 2023-09-27 17:54:47

我在LINQ中有2个查询:

var users = (
    from u in dataContext.KUserNumbers
    select new {
        u.SubscriberAId,
        u.BNumber,
}).Take(10).ToList();

,结果是:

341767 HjbZ8UUO3Ob0ubTk5q2GXg
3451645 9PJwin/OEIxY5G1O3Wm0Ow
645560 3Ps6KvC2haleNT0cm+0eeA
5360374 ktJuCU861efptHPtSnYtIQ
5352388 SJKJVqeOMpW3yAFLJeeVaQ
3027301 0N2+LgMCpOKvNLkAjBPicQ
24697284 XhmdWliLn0U4UI+jPeeVDw
23555123 ox2sYcehRXKJW0y1ppTGRg
28920232 G3/EkrSpTOPjGHme8itApw
3032925 j/LQt0BtMohrLG5wqWQW0g

和第二个:

users = (
    from u in dataContext.KUserNumbers
    select new {
        u.SubscriberAId,
        u.BNumber,
}).Skip(1).Take(10).ToList();

,我想结果应该是这样的:

3451645 9PJwin/OEIxY5G1O3Wm0Ow
645560 3Ps6KvC2haleNT0cm+0eeA
5360374 ktJuCU861efptHPtSnYtIQ
5352388 SJKJVqeOMpW3yAFLJeeVaQ
3027301 0N2+LgMCpOKvNLkAjBPicQ
24697284 XhmdWliLn0U4UI+jPeeVDw
23555123 ox2sYcehRXKJW0y1ppTGRg
28920232 G3/EkrSpTOPjGHme8itApw
3032925 j/LQt0BtMohrLG5wqWQW0g
additional one row

,因为我跳过一行。但结果却完全不同:

0 //+SDiKdXKBYAoicCWj7Bw
0 //03hO7doOCyhiopFJ82+w
0 //1iwyah26fjsJrQicb5pA
0 //3KaH4CBH2cI9ACwWf03Q
0 //4mtbXsQIg+QzcqTShPsw
0 //4O6INt73MsCRB6LV480A
0 //8zOGzTdDo7RMIoJLA0Mg
0 //CfYwcShDAgqbq3OCY8Nw
0 //cl71U4qnNfIrXwhsi5WQ
0 //CUIHrC0qHfS10AIihnKw

这种行为的原因是什么?

谢谢你的帮助

编辑:

如果我在select语句后添加orderbysubscriberaid,我得到:

0 Pj5U5pJzrZn4e2Wr4r0H6Q
0 iVu3fam6j3TRbMGdngTtuw
0 i5STtn65LZE7tJfMUPkhug
0 DyhCFKAp5oe0mm5T2Glgpw
0 GaI7ltFJkVeXjMRXShQyLg
0 uneqHdkaBBMeY4Eir7ySZw
0 BAVlunfU4tak4PFY2OxeNg
0 rd4EDeeMUJ/zKDs1IX+Y5w
0 71H3NKg3wLr3/3Iq0HDcEw
0 EeSuYD+003J0g0/ysVteHA
0 nLGfZFEtGnQeJ4I6P8Jy3w
0 B2i5pv26ZzCgi3DISay+Ag
0 57foBJuQV/+6czziRPNQ1A
0 EBBzbvtSDk+T34m+x3F96A
0 BRWpIbeMGQdh/3MANk4AXw
0 0MiqFyqiPpKarJoj/99uMw
0 AdZ6RAHLY86Qe0OG8aZfkw
0 ISSsqPVacX7RQtEwLEWTvw
0 1bPIdr1yDzg8e00gkPmXew
0 k7flvu9G8F8ACWY3zDmSuw

更新查询:

var users = (
    from u in dataContext.KUserNumbers
    select new {
        u.SubscriberAId,
        u.BNumber,
}).OrderBy(u => u.SubscriberAId).Take(10).ToList();
sers = (
    from u in dataContext.KUserNumbers
    select new {
        u.SubscriberAId,
        u.BNumber,
}).OrderBy(u => u.SubscriberAId).Skip(1).Take(10).ToList();

或多或少就是linq生成的查询的样子。什么是有趣的,当我使用该查询在管理工作室没有结果返回。0行

 SELECT [SubscriberAId], [BNumber]
FROM (
    SELECT ROW_NUMBER() OVER (ORDER BY [SubscriberAId]) AS [ROW_NUMBER], [SubscriberAId], [BNumber]
    FROM [dbo].[KUserNumber] 
    ) AS [t1]
WHERE [t1].[ROW_NUMBER] BETWEEN 1 + 1 AND 1 + 10
ORDER BY [t1].[ROW_NUMBER]

skip and take是怎么起作用的

至于这些linq方法如何"真正工作",我找到的最好的理解资源是Jon Skeet的《reimplementation linq to Objects》,for Skip/Take:

https://msmvps.com/blogs/jon_skeet/archive/2011/01/02/reimplementing-linq-to-objects-part-23-take-skip-takewhile-skipwhile.aspx

至于为什么你正在运行的两个linq查询有这种效果,我只能预测dataContext。KUserNumbers不以特定的顺序枚举?尝试在两个查询的select语句之后引入一个OrderBy,看看它是否会产生更明显的结果。

如果你喜欢这篇文章,你可以在这里找到整个系列:

http://edulinq.googlecode.com/hg/posts/index.html

当你特别使用linq2sql时,另一个很好的调试资源是Debug Visualizer,它允许你看到将被传递到数据库层的查询。这通常会引起从db请求的任何异常:

http://weblogs.asp.net/scottgu/archive/2007/07/31/linq-to-sql-debug-visualizer.aspx

要回答"为什么"的问题,我建议像这样检查生成的SQL。这将告诉您Skip是如何被解释的。

也就是说,如果跳过计数总是一个相对较小的数字,一个简单实用的解决方案是Take(N+k).ToList().Skip(k) .

哈哈

添加

. then (u=>u. b number)解决了这个问题。这意味着你永远无法确定结果是什么,特别是如果表很大(可能在sql server的多个页面上)。

您需要提供良好的排序(尽量使行不同)