我有一个以下的foreach声明:
foreach (var articleId in cleanArticlesIds)
{
var countArt = context.TrackingInformations.Where(x => x.ArticleId == articleId).Count();
articleDictionary.Add(articleId, countArt);
}
数据库看起来像这样
TrackingInformation(Id, ArticleId --some stuff
Article(Id, --some stuff
我想要做的是从TrackingInformations表中获取所有文章ID。 例如:
ArticleId:1 Count:1
ArticleId:2 Count:8
ArticleId:3 Count:5
ArticleId:4 Count:0
所以我可以拥有dictionary<articleId, count>
Context是Entity Framework DbContext。问题是这个解决方案工作得非常慢(db中有大约10k篇文章,它们应该快速增长)
答案 0 :(得分:4)
尝试下一个查询以收集分组数据,并添加缺少的信息。您可以尝试跳过Select
子句,我不知道EF是否能够以良好的方式处理ToDictionary
。
如果遇到Select n + 1问题(大量数据库请求),您可以在ToList()
和Select
之间添加ToDictionary
步骤,以便提供所有必需的信息进入记忆。
这取决于您的所有映射配置,环境,因此为了获得良好的性能,您需要使用不同的查询进行一些操作。主要方法是在数据库级别尽可能多地聚合尽可能多的数据。
var articleDictionary =
context.TrackingInformations.Where(trackInfo => cleanArticlesIds.Contains(trackInfo.ArticleId))
.GroupBy(trackInfo => trackInfo.ArticleId)
.Select(grp => new{grp.Key, Count = grp.Count()})
.ToDictionary(info => "ArticleId:" + info.Key,
info => info.Count);
foreach (var missingArticleId in cleanArticlesIds)
{
if(!articleDictionary.ContainsKey(missingArticleId))
articleDictionary.add(missingArticleId, 0);
}
答案 1 :(得分:2)
如果TrackingInformation是Article的可导航属性,则可以执行以下操作:
var result=context.Article.Select(a=>new {a.id,Count=a.TrackingInformation.Count()});
将它放入字典也很简单:
var result=context.Article
.Select(a=>new {a.id,Count=a.TrackingInformation.Count()})
.ToDictionary(a=>a.id,a=>a.Count);
如果TrackingInforation不是可导航属性,则可以执行以下操作:
var result=context.Article.GroupJoin(
context.TrackingInformation,
foo => foo.id,
bar => bar.id,
(x,y) => new { id = x.id, Count = y.Count() })
.ToDictionary(a=>a.id,a=>a.Count);