Упрощенный пример: У меня есть таблица с FirstName
, LastName
. Я заинтересован в том, чтобы вернуть всех людей, чье полное приветствие не больше на N, отсортированное по длине. Чтобы добиться этого, у меня есть такой код:Выберите проекцию в Entity Framework и проведите фильтр
var result = await Context.People
.Select(p => new PersonWithSalutation
{
FirstName = p.FirstName,
LastName = p.FirstName,
FullSalutation = p.FirstName + " " + p.LastName
})
.Where(p => p.FullSalutation.Length < maxLength)
.OrderBy(p => p.FullSalutation)
.Take(maxResults)
.ToListAsync();
Запрос выглядит следующим образом:
SELECT TOP (10)
[Project1].[C1] AS [C1],
[Project1].[Name] AS [Name],
[Project1].[Id] AS [Id],
[Project1].[C2] AS [C2]
FROM (SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
1 AS [C1],
...calculated stuff... AS [C2]
FROM [dbo].[People] AS [Extent1]
WHERE ...exactly the same stuff... <= @p__linq__3
) AS [Project1]
ORDER BY [Project1].[C2] ASC
Это делает трюк и генерирует один запрос к базе данных. Проблема заключается в вычисленной проекции, поскольку она появляется дважды в результате запроса: один раз в SELECT
, а затем в предложении WHERE
. Этот пример упрощен, но в моем реальном случае я делаю тяжелые математические операции, которые я бы предпочли рассчитать только один раз. Как вы можете видеть выше, C2 повторно используется в предложении order. Я хотел бы сделать то же самое с предложением WHERE
, которое, как я полагаю, связано с еще одним подзапросом). Как я могу это достичь?
Я предположил бы, SQL Server, чтобы понять, что расчет одинакова и не делать он дважды в этом случае. У вас есть основания полагать, что это так? – John