如何跳过并采取真正的工作?

时间:2011-05-02 14:33:34

标签: c# linq linq-to-sql

我在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语句之后添加orderBy subscriberAId,我得到:

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]

3 个答案:

答案 0 :(得分:3)

至于这些linq方法如何“真正起作用”我发现这种理解的最佳资源是Jon Skeet的Reimplementing 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

答案 1 :(得分:1)

要回答'为什么'的问题,我建议检查生成的SQL like this。这将告诉您如何解释Skip。

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

答案 2 :(得分:1)

哈哈:)

添加

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

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