Можно ли оптимизировать этот запрос EF? - PullRequest
2 голосов
/ 27 мая 2011

Я новичок в Entity Framework и не знаю, когда использовать энергичную загрузку и Include, когда использовать запросы LINQ с Select и когда загружать объекты по требованию. Я также не знаю, когда и когда EF кеширует сущности. (Да, я буду читать документы в конце концов: -)

Я строю систему обмена сообщениями внутри веб-сайта ASP .NET MVC, и производительность будет очень важной. Представьте себе следующий сценарий.

Когда Рианна входит в свой почтовый ящик, ей нужно увидеть список сообщений, каждое из которых содержит имя отправителя и его фотографию. Представьте, что Джон написал стихи Рианны для своей новой песни. В ее почтовом ящике есть сообщение с фотографией Джона. Когда Джон входит в свой почтовый ящик, он видит то же сообщение с именем и фотографией Рианны.

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

private static Func<MyEntities, int, Message> _getMessageByIdQuery = CompiledQuery.Compile(
    ( MyEntities ctx, int messageId ) => ctx.Messages
        .Include( "SenderUser" )
        .Include( "SenderUser.UserProfile.Image" )
        .Include( "RecipientUser" )
        .Include( "RecipientUser.UserProfile.Image" )
        .SingleOrDefault( message => message.ID == messageId ) );

Будет ли этот запрос эффективным? Есть ли способ загрузить SenderUser.UserProfile.Image без загрузки SenderUser, учитывая, что User.ID и UserProfile.UserID один на один? Я полагаю, мне нужно будет использовать LINQ JOIN для этого. Это правильно?

Является ли более эффективным использование LINQ, чтобы избежать загрузки всех полей, когда требуется только одно поле (например, только загрузка ImageID из UserProfile)?

Лучше ли сделать то же самое, используя Load где-нибудь в коде?

Идет ли такой запрос в базу данных каждый раз? Представьте, что мы получили тысячу сообщений от одного человека. Будем ли мы запрашивать его Image каждый раз?

Я использую EF 4 и ASP .NET MVC 3.

Спасибо.

Ответы [ 3 ]

3 голосов
/ 27 мая 2011

Одним из способов будет отправка пользовательских объектов отображения / данных непосредственно из запроса, при этом вам не нужно загружать дополнительные объекты.Пример:

var dto = ctx.Messages
          .Where(whereclause)
          .Select(m=> new DTOTYPE
                         {Id = m.Id, 
                          Content= m.Content, 
                          SenderId = m.SenderUser.Id, 
                          SenderImage = m.SenderUser.UserProfile.Image, 
                          SenderImageId = m.SenderUser.UserProfile.ImageId}) 
                         //more fields if you need any

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

1 голос
/ 27 мая 2011

Используйте проекцию, предложенную в @ AD.Net. При использовании проекции вы можете передавать данные, которые вам действительно нужны, вместо целых объектов, полных свойств, которые вы никогда не используете. Имейте в виду, что это действительно загружает картинки каждый раз, когда вы запрашиваете в базе данных сообщение.

Если вы планируете показывать больше сообщений от одного и того же пользователя, загрузите изображение только один раз в отдельном запросе! Кроме того, действительно ли необходимо, чтобы получатель загрузил свое изображение? Если да, то почему бы не загружать изображение только один раз, когда он входит в систему, и сохранять его, например, в сеансе, вместо того, чтобы загружать одни и те же данные для каждого сообщения в ее почтовом ящике?

0 голосов
/ 27 мая 2011

Никто не может сказать вам, как ваш код будет работать, вам придется тестировать.Да, вы можете избежать загрузки SenderUser, если используете соединение.Посмотрите здесь , если вы хотите узнать, как увидеть сгенерированный SQL-код.

...