我使用Linq to Sql(實際上它是Dynamic Linq to SQL,允許您在運行時爲where子句,orderby等傳遞字符串)但是我得到一些不同的結果,它似乎是基於底層T-SQL是使用TOP關鍵字還是使用BETWEEN。Linq to SQL提供了不同的結果,當使用TOP和
我試圖破解的問題分解成一個小例子,這裏的情景:
我使用一個倉庫模式,簡單地連接2臺與左外下面的方法加入。
public IQueryable<TestGalleryViewModel> FetchGalleryItems()
{
var galleryItems = from painting in Gallery
join artist in Artists
on painting.ArtistID equals artist.ArtistID
into paintingArtists
from artist in paintingArtists.DefaultIfEmpty()
select new TestGalleryViewModel
{
Id = painting.PaintingID,
ArtistName = artist == default(Artist) ? "" : artist.Surname + " " + artist.Forenames,
};
return galleryItems;
}
然後我有一個使用FetchGalleryItems方法一個小的測試方法:
var query = respository.Test_FetchGalleryItems().Where("ArtistName.Contains(\"Adams Charles James\")");
var orderedlist = query.OrderBy("ArtistName asc");
var page1 = orderedlist.Skip(0).Take(5);
var page2 = orderedlist.Skip(5).Take(5);
的orderedList包含以下基本的價值觀:
176 ADAMS Charles James
620 ADAMS Charles James
621 ADAMS Charles James
660 ADAMS Charles James
683 ADAMS Charles James
707 ADAMS Charles James
735 ADAMS Charles James
739 ADAMS Charles James
740 ADAMS Charles James
741 ADAMS Charles James
這是我期望的那樣。但第1頁包含
707 ADAMS Charles James
683 ADAMS Charles James
660 ADAMS Charles James
621 ADAMS Charles James
620 ADAMS Charles James
正如你可以看到的是不第5個項目。第2頁包含
707 ADAMS Charles James
735 ADAMS Charles James
739 ADAMS Charles James
740 ADAMS Charles James
741 ADAMS Charles James
WHIS是我所期望的,它是項目6至10
底層的T-SQL的第1頁是
SELECT TOP (5) [t3].[PaintingID] AS [Id], [t3].[value] AS [ArtistName]
FROM (
SELECT [t0].[PaintingID],
(CASE
WHEN [t2].[test] IS NULL THEN CONVERT(NVarChar(101),'')
ELSE ([t2].[Surname] + ' ') + [t2].[Forenames]
END) AS [value]
FROM [dbo].[Gallery] AS [t0]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t1].[ArtistID], [t1].[Surname], [t1].[Forenames]
FROM [dbo].[Artists] AS [t1]
) AS [t2] ON [t0].[ArtistID] = ([t2].[ArtistID])
) AS [t3]
WHERE [t3].[value] LIKE '%Adams Charles James%'
ORDER BY [t3].[value]
注意到它的使用TOP(5)
page2的底層T-SQL是
SELECT [t4].[PaintingID] AS [Id], [t4].[value] AS [ArtistName]
FROM (
SELECT ROW_NUMBER() OVER (ORDER BY [t3].[value], [t3].[Surname], [t3].[Forenames]) AS [ROW_NUMBER], [t3].[PaintingID], [t3].[value]
FROM (
SELECT [t0].[PaintingID],
(CASE
WHEN [t2].[test] IS NULL THEN CONVERT(NVarChar(101),'')
ELSE ([t2].[Surname] + ' ') + [t2].[Forenames]
END) AS [value], [t2].[Surname], [t2].[Forenames]
FROM [dbo].[Gallery] AS [t0]
LEFT OUTER JOIN (
SELECT 1 AS [test], [t1].[ArtistID], [t1].[Surname], [t1].[Forenames]
FROM [dbo].[Artists] AS [t1]
) AS [t2] ON [t0].[ArtistID] = ([t2].[ArtistID])
) AS [t3]
WHERE [t3].[value] LIKE '%Adams Charles James%'
) AS [t4]
WHERE [t4].[ROW_NUMBER] BETWEEN 5 + 1 AND 5 + 5
ORDER BY [t4].[ROW_NUMBER]
注意到它的使用BETWEEN
當我粘貼T-SQL命令插入到的SQL Express Management Studio中,我得到我所描述的結果。如果我用的第2頁T-SQL和修正線
WHERE [t4].[ROW_NUMBER] BETWEEN 5 + 1 AND 5 + 5
是
WHERE [t4].[ROW_NUMBER] BETWEEN 1 AND 5
我得到我所期待的第一頁的結果。即前5個項目。
176 ADAMS Charles James
620 ADAMS Charles James
621 ADAMS Charles James
660 ADAMS Charles James
683 ADAMS Charles James
所以,簡而言之,當T-SQL使用之間,而不是TOP我得到我預期的效果。我在我的應用程序中使用過濾(where子句),排序(orderBy)和分頁(skip and take),並且需要相當一般地處理這個問題。
- 有沒有辦法迫使LINQ使用 的之間語法而不是 TOP?
- 我是否應該以不同的方式接近此 ?
道歉的長期職位。
問候, 西蒙
請注意,您在第二個SQL查詢中有不同的Order By Clause。嘗試評估var orderedlist = query.OrderBy(「ArtistName asc」)。ToList();首先是 。然後從那裏獲取頁面。 – 2010-01-05 14:45:20