#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
.