Замедленная загрузка дочерней таблицы Sum Entity Framework

#c# #sql #performance #entity-framework #linq

#c# #sql #Производительность #entity-framework #linq

Вопрос:

У меня возникли проблемы с производительностью с методом sum в entity Framework. Чтобы лучше объяснить это, это моя структура таблицы:

  ---- -------- --------- -------     ----------- ----------- ------- 
| Id |  Name  | Company | Color |   | ArticleId | Purchaser | Price |
 ---- -------- --------- -------     ----------- ----------- ------- 
|  1 | iPhone | Apple   | Black |   |         1 | Bob       |   350 |
|  2 | iPad   | Apple   | Grey  |   |         1 | Mat       |   220 |
 ---- -------- --------- -------    |         2 | Ivy       |   450 |
                                     ----------- ----------- ------- 
  

Это связанная модель для таблицы Article:

 public int Id { get; set; }
public string Name { get; set; }
...
[NotMapped]
public decimal? TotalAmount { get; set; }
public virtual ICollection<Purchase> PurchaserList { get; set; }
  

Используя отложенную загрузку, entity framework автоматически загрузит всех связанных покупателей. Затем я просто суммирую цену за каждую статью и устанавливаю ее равной свойству TotalAmount:

 articleList = dbContext.Article.Where(x => x.CompanyId == 10).ToList();

foreach(var article in articleListe)
    article.TotalAmount= article.PurchaserList.Sum(x => x.Price);
  

Однако для таблицы, содержащей всего 100 записей, это занимает около 4 секунд. Конечно, это слишком медленно, и мне нужно немного ускорить это. Есть ли у кого-нибудь какие-либо предложения или что-нибудь, что я могу улучшить, чтобы сделать это быстрее?

Редактировать:

Как упоминалось rad, изменение ее с отложенной загрузки на ускоренную загрузку улучшило время загрузки с 4 секунд до 0,17 секунды. Я удалил виртуальную обработку клавиш и изменил свой код следующим образом:

 articleList = dbContext.Article.Where(x => x.CompanyId == 10).Include(x => x.PurchaserList).ToList();
  

Ответ №1:

Используйте ускоренную загрузку ( Include ) вместо отложенной загрузки.
Отложенная загрузка не является хорошим выбором в вашем сценарии, потому что для каждого PurchaserList извлечения выполняется новое подключение к базе данных (т. Е. 100 подключений в вашем примере), и это требует времени для ввода-вывода базы данных.
Вы можете отслеживать запросы и соединения с помощью Sql Profiler.

Комментарии:

1. Большое спасибо!! Теперь это занимает всего 170 мс. Итак, мне интересно, есть ли какой-либо случай, когда я бы выбрал отложенную загрузку вместо быстрой загрузки?

2. Да, отложенная загрузка и ускоренная загрузка — оба полезных параметра, однако вам нужно быть осторожным при их использовании. Я предпочитаю использовать отложенную загрузку, когда с основным объектом извлекается только один или несколько связанных объектов, но очень опасно использовать отложенную загрузку в циклах.

3. Кроме того, отложенная загрузка предпочтительнее быстрой загрузки, когда вам не нужно извлекать все связанные данные сразу.

Ответ №2:

Вы должны попробовать это, чтобы получить свою сумму непосредственно из базы данных, используя прогнозы:

 articleListSum = dbContext.Article.Where(x => x.CompanyId == 10).Select(x => x.PurchaserList.Select(y => y.Price)).DefaultIfEmpty(0).Sum();
  

Комментарии:

1. Это было бы итогом всех покупок для всех товаров у одной и той же компании. Оператору требуется сумма для каждой статьи. Также для того, чтобы это работало, вам нужен SelectMany .