繁体   English   中英

LINQ,Skip和Take订购

[英]LINQ, Skip and Take ordering

我正在使用Take和Skip进行一些测试,我发现:

var objects = (from c in GetObjects() orderby c.Name select c);
var skipTake = objects.Skip(5).Take(10).ToList();
var takeSkip = objects.Take(10).Skip(5).ToList();

GetObjects()返回由NHibernate生成的IQueryable(3.3.3GA,使用SQL Server 2008 R2 DB)。
skipTake和takeSkip包含10个对象的完全相同的序列。
但如果我写

var objects = (from c in GetObjects() orderby c.Name select c).ToList();
var skipTake = objects.Skip(5).Take(10).ToList();
var takeSkip = objects.Take(10).Skip(5).ToList();

skipTake包含与上例相同的序列,而takeSkip包含仅5个对象的不同序列。

将Take和Skip调用应用于IQueryable时会重新排序吗?
我很乐意对此有所了解。

提前致谢。

看起来这是由于特定版本的nhibernate中的一个错误:

http://sourceforge.net/p/nhibernate/news/2013/03/nhiberate-333ga-released/

注意:在3.3.3.CR1之前的版本中,LINQ Take()方法的处理存在缺陷 - 无论在查询的哪个位置放置Take(),它总是被应用,就像它被放置在最后一样。 3.3.3修复此问题,以便Take()现在正确遵循.Net语义。 也就是说,在3.3.3中,以下查询现在可能会给出不同的结果:

session.Query<Foo>.OrderBy(...).Take(5).Where(...);
session.Query<Foo>.Where(...).OrderBy(...).Take(5);

从3.3.3开始,第一个查询将生成一个子查询,以便在where子句之前正确应用行限制。

将Take和Skip调用应用于IQueryable时会重新排序吗? 我很乐意对此有所了解。

我认为这个问题的答案应该这样制定:

skipTake是跳过IQueriable的前5个元素并取下10个元素的结果。因此,例如在1到20的有序数字列表中,skipTake将是子列表6 - > 15。

takeSkip是获取IQueriable的前10个元素然后跳过子列表的前5个元素(!)的结果。 因此,使用上一个示例中的列表,takeSkip将是子列表6 - > 10。

对于观察的第一部分(skipTake和takeSkip包含相同的10个元素),这应该被视为NHibernate实现中的错误行为(或者甚至可能是错误)。

首先,我发现@ https://stackoverflow.com/users/2617732/rdans答案与您的具体示例无关,因为您没有在Take之后应用where子句。

也就是说,在示例A中, skipTaketakeSkip应该生成相同的SQL,它将选择第5行之后的前10行(对于SQL服务器,例如将使用ROW_NUMBER OVER(...) )。

在我看来,在示例B中,您尝试不在IQuerable上执行TakeSkip ,而是在System.Collections.Generic.List<> (当然不是NHibernate区域)上执行。

在这种情况下, objects具有N个元素。

skipTake将首先Skip 10个元素,然后从生成的枚举(枚举N-10个元素)中Take前5个元素。

在给定结果已经排序的情况下, skipTakeToList的结果应该与示例A相同。

另一方面, takeSkip首先Take 10个元素并从生成的枚举(枚举超过10个元素) Skip前5 元素。

那就是那个

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM