簡體   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