Я пытаюсь добавить функциональность ROW_NUMBER в EF Core и фильтровать по ней.
После добавления пользовательской функции она отлично работает в Select
, но не работает в Where
из-за неправильной формы SQL.
Linq:
var query = dbContext.OrderItems
.Select(i => new
{
i.Name,
RowNumber = EF.Functions.RowNumber(i.ProductId)
})
.Where(i => i.RowNumber == 1);
Переводится в:
SELECT
i.NAME,
ROW_NUMBER() OVER(ORDER BY i.ProductId) AS RowNumber
FROM
OrderItems AS i
WHERE
ROW_NUMBER() OVER(ORDER BY i.ProductId) = CAST(1 AS bigint)
Ошибка:
Microsoft.Data.SqlClient.SqlException (0x80131904): Windowed functions can only appear in the SELECT or ORDER BY clauses.
Чтобы исправить это SQL , Мне нужно создать подзапрос:
SELECT
t.NAME,
t.RowNumber
FROM (
SELECT
i.NAME,
ROW_NUMBER() OVER(ORDER BY i.ProductId) AS RowNumber
FROM
OrderItems AS i
) t
WHERE
t.RowNumber = CAST(1 AS bigint)
Я нашел статью о том, как сделать это в EF Core 2.
Возможно, самый простой способ - это ввести метод, который дает EF подсказку, что предыдущий запрос должен быть подзапросом. К счастью, у нас не так много, потому что внутри метод AsQueryable (или, скорее, выражение, связанное с ним) делает именно это.
https://www.thinktecture.com/en/entity-framework-core/making-rownumber-more-useful-in-2-1/
Но этот подход ничего не делает в EF Core 3.1
Есть ли способ создать подзапрос?