Я использую Linq to Sql (на самом деле это Dynamic Linq to SQL, который позволяет передавать строки во время выполнения для операторов where, orderby и т. Д.) Но я получаю некоторые другие результаты, и кажется, что они основаны на том, базовый T-SQL использует ключевое слово TOP или использует BETWEEN.
Я попытался разбить проблему на небольшой пример, вот сценарий:
Я использую шаблон репозитория и следующий метод, который просто объединяет 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);
orderList содержит следующие базовые значения:
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
То, что я ожидал, это пункты с 6 по 10.
Базовым T-SQL для page1 является
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)
Базовый T-SQL для page2:
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]
Обратите внимание, что он использует МЕЖДУ
Когда я вставляю команды T-SQL в SQL Express Management Studio, я получаю результаты, которые я описал. Если бы я использовал T2-SQL page2 и изменил строку
WHERE [t4].[ROW_NUMBER] BETWEEN 5 + 1 AND 5 + 5
будет
WHERE [t4].[ROW_NUMBER] BETWEEN 1 AND 5
Я получил результаты, которые я ожидал для страницы1. первые 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) и разбиение по страницам (пропустить и принять) во всем приложении, и мне нужно обрабатывать это довольно обобщенно.
- Есть ли способ заставить LINQ использовать
МЕЖДУ синтаксисом вместо
TOP ?
- Должен ли я приближаться к этому
иначе?
Извинения за длинный пост.
С уважением,
Simon