詳解LINQ to SQL分頁問題 不同版本對比
從 .NET Framework 有了 LINQ,SQL 分頁有了新的選擇,那就是簡單使用 Skip 及 Take 方法。當然,別忘了加上排序。本以為對此沒有什么可懷疑的,殊不知在我們的產(chǎn)品 SE 中卻碰到了很奇怪的一個問題:對某張表的執(zhí)行分頁查詢,有一條數(shù)據(jù)在所有分頁中均沒有出現(xiàn)。通過查看真正執(zhí)行的 SQL 發(fā)現(xiàn),SqlProvider 翻譯的第一頁的 SQL 用的是 TOP N,而其他分頁用的是 ROW_NUMBER 函數(shù) + 范圍限定。多的不說,僅從二者的不同,我就覺得其結(jié)果不能劃等號。但是,在另建的測試中,我發(fā)現(xiàn)二者結(jié)果沒有什么問題。百思不得其解之余,也只能自我安慰說 MS 會保證二者邏輯一致,至于為何用不同的方法,那是出自性能的考慮。
直至今日,突然想起這個問題,就 GOOGLE 了一把,看看是否有同學碰到這樣的問題。結(jié)果就找到了: 利用 LINQ to SQL 對資料做分頁時應注意的事 ( 重要 ),其結(jié)論就是要注意使用 OrderBy 方法,否則數(shù)據(jù)邏輯不對。然后按其說的進行了測試,實際情況確實如此,但是我也加了排序,為何還有問題呢?我暫時沒辦法重現(xiàn)這個問題,因為業(yè)務數(shù)據(jù)在變化,現(xiàn)在看來又正常了。
解鈴還需系鈴人,只能期望 MS 在新的版本中解決這個問題了。辦法很簡單:首頁不用 TOP N,而是統(tǒng)一使用 ROW_NUMBER 函數(shù)。由于 SE 還服務器端的代碼沒有使用 .NET Framework 4 編譯,所以也就一直沒有嘗試。今天測試了一下,發(fā)現(xiàn)在 NF 4.0 中,已經(jīng)修正了這個問題,結(jié)果如下:
- SELECT [t1].[ID], [t1].[Name], [t1].[CreateTime]
- FROM (
- SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID], [t0].[Name], [t0].[CreateTime]
- ) AS [ROW_NUMBER], [t0].[ID], [t0].[Name], [t0].[CreateTime]
- FROM [dbo].[TableA] AS [t0]
- ) AS [t1]
- WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
- ORDER BY [t1].[ROW_NUMBER]
- -- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [0]
- -- @p1: Input Int (Size = -1; Prec = 0; Scale = 0) [5]
- -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
- SELECT [t1].[ID], [t1].[Name], [t1].[CreateTime]
- FROM (
- SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID], [t0].[Name], [t0].[CreateTime]
- ) AS [ROW_NUMBER], [t0].[ID], [t0].[Name], [t0].[CreateTime]
- FROM [dbo].[TableA] AS [t0]
- ) AS [t1]
- WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
- ORDER BY [t1].[ROW_NUMBER]
- -- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [5]
- -- @p1: Input Int (Size = -1; Prec = 0; Scale = 0) [5]
- -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 4.0.30319.1
比對一下:
- SELECT TOP (5) [t0].[Name], [t0].[ID], [t0].[CreateTime]
- FROM [dbo].[TableB] AS [t0]
- ORDER BY [t0].[ID]
- -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926
- SELECT [t1].[Name], [t1].[ID], [t1].[CreateTime]
- FROM (
- SELECT ROW_NUMBER() OVER (ORDER BY [t0].[ID]) AS [ROW_NUMBER], [t0].[Name],
- [t0].[ID], [t0].[CreateTime]
- FROM [dbo].[TableB] AS [t0]
- ) AS [t1]
- WHERE [t1].[ROW_NUMBER] BETWEEN @p0 + 1 AND @p0 + @p1
- ORDER BY [t1].[ROW_NUMBER]
- -- @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [5]
- -- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [5]
- -- Context: SqlProvider(Sql2008) Model: AttributedMetaModel Build: 3.5.30729.4926
NF 4.0 出來有一段時間了,只是我比較懶,一直沒有測試過這個問題。直到在看到 LINQ to SQL changes in .NET 4.0 其中提及的 Skip(0) 才有此次測試。所以,還在用 3.5 的兄弟們,趕緊升級到 4.0 吧。
原文標題:LINQ to SQL 分頁問題
鏈接:http://www.cnblogs.com/AutumnalRiver/archive/2010/06/13/1757891.html
【編輯推薦】