Мне очень сложно настроить один из моих Entity Framework
сгенерированных запросов в моем приложении. Это очень простой запрос, но по какой-то причине EF
использует несколько внутренних подзапросов, которые, похоже, работают ужасно в DB
вместо использования объединений.LINQ и Entity Framework - избегайте подзапросов
Вот мой LINQ код:
Projects.Select(proj => new ProjectViewModel()
{
Name = proj.Name,
Id = proj.Id,
Total = proj.Subvalue.Where(subv =>
subv.Created >= startDate
&& subv.Created <= endDate
&&
(subv.StatusId == 1 ||
subv.StatusId == 2))
.Select(c => c.SubValueSum)
.DefaultIfEmpty()
.Sum()
})
.OrderByDescending(c => c.Total)
.Take(10);
EF создает очень сложный запрос с несколькими подзапросами, который имеет ужасную производительность запроса, как это:
SELECT TOP (10)
[Project3].[Id] AS [Id],
[Project3].[Name] AS [Name],
[Project3].[C1] AS [C1]
FROM (SELECT
[Project2].[Id] AS [Id],
[Project2].[Name] AS [Name],
[Project2].[C1] AS [C1]
FROM (SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name],
(SELECT
SUM([Join1].[A1]) AS [A1]
FROM (SELECT
CASE WHEN ([Project1].[C1] IS NULL) THEN cast(0 as decimal(18)) ELSE [Project1].[SubValueSum] END AS [A1]
FROM (SELECT 1 AS X) AS [SingleRowTable1]
LEFT OUTER JOIN (SELECT
[Extent2].[SubValueSum] AS [SubValueSum],
cast(1 as tinyint) AS [C1]
FROM [dbo].[Subvalue] AS [Extent2]
WHERE ([Extent1].[Id] = [Extent2].[Id]) AND ([Extent2].[Created] >= '2015-08-01') AND ([Extent2].[Created] <= '2015-10-01') AND ([Extent2].[StatusId] IN (1,2))) AS [Project1] ON 1 = 1
) AS [Join1]) AS [C1]
FROM [dbo].[Project] AS [Extent1]
WHERE ([Extent1].[ProjectCountryId] = 77) AND ([Extent1].[Active] = 1)
) AS [Project2]
) AS [Project3]
ORDER BY [Project3].[C1] DESC;
Время выполнения запроса, генерируемый ФВ ~10 seconds
, Но когда я пишу запрос вручную следующим образом:
select
TOP (10)
Proj.Id,
Proj.Name,
SUM(Subv.SubValueSum) AS Total
from
SubValue as Subv
left join
Project as Proj on Proj.Id = Subv.ProjectId
where
Subv.Created > '2015-08-01' AND Subv.Created <= '2015-10-01' AND Subv.StatusId IN (1,2)
group by
Proj.Id,
Proj.Name
order by
Total DESC
Время исполнения около момента; ниже 30ms
.
Проблема явно лежит в моей способности писать хорошие EF
запросов с LINQ, но независимо от того, что я пытаюсь сделать (с помощью Linqpad
для тестирования) Я просто не могу написать подобный производительный запрос с LINQ\EF
, как я могу писать вручную. Я пробовал запрашивать таблицу SubValue и таблицу Project, но конечный результат в основном такой же: несколько неэффективных вложенных подзапросов, а не одно соединение, выполняющее работу.
Как написать запрос, который имитирует написанную рукой SQL
, показанную выше? Как я могу управлять фактическим запросом, созданным EF
? И самое главное: как я могу получить Linq2SQL
и Entity Framework
, чтобы использовать Joins
, когда я хочу вместо вложенных подзапросов.
С ** LINQ ** вы probalby с помощью 'DataContext'. Посмотрите на свойство DataContext.LoadOptions [здесь] (https: // msdn.microsoft.com/en-us/library/system.data.linq.datacontext.loadoptions%28v=vs.110%29.aspx) .. –
set context.ObjectTrackingEnabled = false, вы получите огромное улучшение. –
@JanUnld благодарит за предложение, но я не уверен, как это поможет в этой конкретной проблеме? Не могли бы вы объяснить это более подробно? – veturi