[英]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中, skipTake
和takeSkip
應該生成相同的SQL,它將選擇第5行之后的前10行(對於SQL服務器,例如將使用ROW_NUMBER OVER(...)
)。
在我看來,在示例B中,您嘗試不在IQuerable
上執行Take
和Skip
,而是在System.Collections.Generic.List<>
(當然不是NHibernate區域)上執行。
在這種情況下, objects
具有N個元素。
skipTake
將首先Skip
10個元素,然后從生成的枚舉(枚舉N-10個元素)中Take
前5個元素。
在給定結果已經排序的情況下, skipTake
的ToList
的結果應該與示例A相同。
另一方面, takeSkip
首先Take
10個元素並從生成的枚舉(枚舉超過10個元素) Skip
前5 個元素。
那就是那個
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.