2013-08-09 3 views
1

Я новичок в LINQ, я начал писать этот запрос:оптимизируют LINQ запрос с соответствующими субъектами

 var dProjects = Projects 
     .Select(p => new Models.Project { 
      ProjectID = p.ProjectID, 
      Status = p.Status, 
      ExpiresOn = p.ExpiresOn, 
      LatestComments = p.ProjectComments 
           .OrderByDescending(pc => pc.CreatedOn) 
           .Select(pc => pc.Comments) 
           .FirstOrDefault(),     
      ProjectFileIDs = p.ProjectFiles 
           .Select(pf => pf.BinaryFileID) 
           .AsQueryable() 
     }) 
     .AsQueryable<Models.Project>(); 

Я уже знаю, этот запрос будет работать очень медленно, поскольку связанные объекты, такие как ProjectComments и ProjectFiles будут создавать вложенные выбирает, хотя он работает и дает мне правильные результаты, которые мне нужны.

Как я могу оптимизировать этот запрос и получать те же результаты? Одно из моих предположений будет использовать inner join, но ProjectComments и ProjectFiles уже имеют отношения в базе данных через ключи, поэтому не уверены, чего мы можем достичь, установив отношения снова.

В принципе, необходимо знать, какой из них лучше всего подходит с точки зрения производительности. Стоит отметить, что я сортирую ProjectComments и беру только последнее. Должен ли я использовать комбинацию join и group by into? Помощь будет высоко оценена. Благодарю.

ОБНОВЛЕНО:

Извините, если я не был достаточно ясно, что я пытаюсь сделать. В принципе, у меня есть сетка, которая показывает список проектов с последними комментариями проекта и список всех файлов, связанных с проектом, поэтому пользователи могут щелкнуть по этим ссылкам и фактически открыть эти документы. Таким образом, запрос, который я выше работает и он показывает следующее в сетке:

ID проекта (из таблицы Project) Статус (Из таблицы Project) ExpiresOn (Из таблицы Project) LatestComments (последнюю запись из Таблица ProjectComments, которая имеет идентификатор проекта как внешний ключ) ProjectFileIDs (список идентификаторов файлов из таблицы ProjectFiles с идентификатором проекта как внешним ключом - я использую эти идентификаторы файлов и создаю ссылки, чтобы пользователи могли открывать эти файлы).

Итак, все работает, у меня есть все настройки, но запрос выполняется очень медленно. Прямо сейчас у нас очень мало данных (только тестовые данные), но как только это запущено, я ожидаю много пользователей/данных, и поэтому я хочу оптимизировать этот запрос до лучших результатов, прежде чем он начнет жить. Итак, цель здесь - в основном оптимизировать. Я уверен, что это не лучший подход, потому что это создаст вложенные select.

+0

Вы действительно не объяснили, что вы пытаетесь достичь с помощью этого запроса - попробуйте добавить более подробную информацию, чтобы люди, которые не знают о том, над чем вы работаете, все еще могут помочь: что это такое вам нужно как вывод, есть ли данные, полученные этим запросом, которые вам не нужны, какой бит замедляет его? –

+0

Вы используете EntityFramework? – devuxer

+0

Да, я использую EF – user2611218

ответ

0

Получите ли вы повышение эффективности, если вы добавите Include заявления перед Select?

Пример:

var dProjects = Projects 
    .Include(p => p.ProjectComments) 
    .Include(p => p.ProjectFiles) 

Include позволяет все соответствующие ProjectComments и ProjectFiles быть жадно загружены. См. Loading Related Entities для более подробной информации.

2

В Entity Framework вы можете значительно повысить производительность запросов, вернув объекты обратно в виде графика объектов вместо проекции. Entity Framework чрезвычайно эффективна для оптимизации всех, кроме самых сложных SQL-запросов, и может использовать отложенную загрузку «Eager» по сравнению с «Lazy» Загрузка (не загружая связанные элементы из db, пока они фактически не будут доступны). Это MSDN reference - хорошее место для начала.

Насколько ваш конкретный запрос, то, вы могли бы использовать эту технику что-то вроде следующего:

var dbProjects = yourContext.Projects 
        .Include(p => p.ProjectComments 
           .OrderByDescending(pc => pc.CreatedOn) 
           .Select(pc => pc.Comments) 
           .FirstOrDefault() 
          ) 
        .Include(p => p.ProjectFileIDs) 
        .AsQueryable<Models.Project>(); 

Примечание .Include() используется подразумевает жадная загрузка.

С MDSN Reference on Loading Related Objects,

Вопросы производительности

Когда вы выбираете шаблон для связанных с загрузкой сущностей, рассмотрим поведение каждого подхода в отношении количества и сроков соединений к источника данных по сравнению с количеством возвращаемых данных и сложностью использования одного запроса. Нежелательная загрузка возвращает все связанные объекты вместе с запрошенными объектами в одном запросе. Это означает, что, хотя есть только одно соединение с источником данных, в исходном запросе возвращается больший объем данных. Кроме того, пути запроса приводят к более сложному запросу из-за дополнительных объединений, которые требуются в запросе, который выполняется против источника данных.

Явная и ленивая загрузка позволяет отложить запрос на данные связанных объектов до тех пор, пока эти данные не понадобятся. Это дает менее сложный первоначальный запрос, который возвращает меньше полных данных. Однако каждая последующая загрузка связанного объекта делает соединение с источником данных и выполняет запрос. В случае ленивой загрузки это соединение происходит всякий раз, когда осуществляется доступ к свойствам навигации, и связанный объект еще не загружен.

Смежные вопросы