簡體   English   中英

Skip()和Take()作為可枚舉與可查詢

[英]Skip() and Take() as Enumerable vs as Queryable

我最近在嘗試使用LINQ語句跳過和接收時遇到錯誤。

我的陳述看起來像這樣。

DbConxtext.MyTable.Get(c => c.UserID == id)
    .OrderBy(orderProperty).Skip(index).Take(length).ToList();

這給了我這個錯誤

'OFFSET'附近的語法不正確。\\ r \\ n FETCH語句中選項NEXT的無效用法

我發現這是由於OFFSET NEXT和FETCH在sql server 2008上不起作用引起的,但是我知道我在代碼的其他位置使用了分頁,並且它們都可以正常工作。

有效的方法與這一方法之間的區別在於, SkipTake是有效方法的擴展,是Enumerable的擴展,無效方法的擴展是Queryable。

因此,向查詢添加AsEnumerable()對我來說解決了這個問題。 這似乎生成了使用SELECT TOP(10)而不是OFFSETFETCH的 SQL。

編輯: 再次閱讀此書后,我意識到AsEnumerable將不會生成其他SQL。 相反,它將執行查詢並在內存中執行“跳過接管”。

DbConxtext.MyTable.Get(c => c.UserID == id)
    .OrderBy(orderProperty).AsEnumerable().Skip(index).Take(length).ToList();

我的問題是,使用“跳過”和“采用作為Enumerable與Queryable的擴展”之間有什么區別?

以及為什么EF決定在這兩種情況之間生成不同的SQL。

使用SkipTake as EnumerableQueryable擴展之間有什么區別?

當您在實現IQueryable的類型上調用SkipTake時,將綁定Queryable擴展方法,並且基礎的Linq提供程序(例如Linq-to-Entities)將處理Skip和/或Take並將其轉換為基礎的命令數據提供者(例如SQL語句)。 直到運行時,才知道提供程序是實際支持它們還是正確處理它們。

當您在實現IEnumerable的類型上調用它們(但不是IQueryable )時,將綁定Enumerable擴展方法,該方法僅處理Queryable查詢生成的內存集合中的命令。

EF為什么決定在兩種情況下生成不同的SQL。

在第二種情況下,生成的SQL查詢僅合並命令,直到您注入AsEnumerable()為止。 這就是EF提供程序所能看到的全部。 從那時起,這些命令將綁定到Enumerable擴展方法,並將在內存中處理其余命令。

這似乎生成使用SELECT TOP(10)的SQL。

我對此表示高度懷疑。 應該發生的是,SQL查詢將返回所有記錄,但是Take生成的內存中迭代器將僅返回前十個。

如果要為SQL 2008數據庫正確處理“跳過”和“取走”,請參閱此問題以獲取替代解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM