我正在使用Take和Skip进行一些测试,我发现:
sudo a2enmod access_compat
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);
var skipTake = objects.Skip(5).Take(10).ToList();
var takeSkip = objects.Take(10).Skip(5).ToList();
skipTake包含与上例相同的序列,而takeSkip包含仅5个对象的不同序列。
当Take和Skip调用应用于IQueryable时会重新排序吗? 我很乐意对此有所了解。
提前致谢。
答案 0 :(得分:2)
看起来这是由于特定版本的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子句之前应用行限制。
答案 1 :(得分:0)
当Take和Skip调用应用于a时,会重新排序 IQueryable的?我很乐意对此有所了解。
我认为这个问题的答案应该这样制定:
skipTake 是跳过IQueriable的前5个元素并取下一个10的结果。因此,例如在1到20的有序数字列表中,skipTake将是子列表6 - &GT; 15。
takeSkip 是获取IQueriable的前10个元素然后跳过子列表的前5个元素(!)的结果。因此,使用前一个示例中的列表,takeSkip将是子列表6 - &gt; 10。
对于观察的第一部分(skipTake和takeSkip包含相同的10个元素),这应该被视为NHibernate实现中的错误行为(或者甚至可能是错误)。
答案 2 :(得分:0)
首先,我发现@ https://stackoverflow.com/users/2617732/rdans答案与您的具体示例无关,因为您未在Take
之后应用where子句。
也就是说,在示例A中,skipTake
和takeSkip
应该生成相同的SQL,它将选择第5行之后的前10行(对于SQL服务器,例如,它将与ROW_NUMBER OVER(...)
)。
在我看来,在示例B中,您尝试执行Take
和Skip
不是IQuerable
而是System.Collections.Generic.List<>
(当然不是NHibernate)境)。
在这种情况下,objects
有N个元素。
skipTake
将首先Skip
10个元素,并从最终的枚举(枚举N-10个元素)然后Take
前5个元素。
鉴于此后结果已经排序,skipTake
s ToList
的结果应与示例A相同。
takeSkip
首先是Take
个10个元素,并且从结果枚举(其中列出 10 元素)Skip
开始是前5个元素。
那就是那个