我目前有这段代码:
foreach (var newsToPolitician in news.NewsToPoliticians)
{
var politician = newsToPolitician.Politician;
var votes = (from s in db.Scores
where o.IDPolitician == politician.IDPolitician
&& o.IDNews == IDNews
group o by o.IDAtribute
into g
select new{
Atribute= g.Key,
TotalScore= g.Sum(x => x.Score)
}).ToList();
}
它工作正常,但我想避免在foreach
循环中对我的数据库进行多次查询。
我的表Scores
看起来像这样:
IDScore | IDNews | IDUser | IDPolitician | IDAtribute | Score
1 40 1010 35 1 1
2 40 1010 35 2 -1
3 40 1002 35 1 1
4 40 1002 35 2 1
5 40 1002 40 1 -1
...
我的目标是在新闻中汇总所有政治家的所有分数。一则新闻最多可以有7位政治家
在foreach
循环中调用我的数据库最多七次是否昂贵。我知道这不是最佳实践,所以我感兴趣的是有没有办法在这种特殊情况下避免它并调用数据库然后在服务器端处理它?</ p>
答案 0 :(得分:2)
更新 - 由于用户注释已重新设置以尝试确保服务器上的聚合。
在这种情况下,我们可以通过IDPolitician
和IDAttribute
对服务器进行分组,然后在本地提取ToLookup
组,如下所示:
var result = db.Scores.Where(s => s.IDNews == IDNews)
.Where(s => news.NewsToPoliticians
.Select(n => n.Politician.IDPolitician)
.Contains(s.IDPolitician))
.GroupBy(s => new
{
s.IDPolitician,
s.IDAttribute
},
(k,g ) => new
{
k.IDPolitician,
k.IDAttribute,
Sum = g.Sum(x => x.Score)
})
.ToLookup(anon => anon.IDPolitician,
anon => new { anon.IDAttribute, anon.Sum })
遗产 -
你想在这里使用GroupJoin
,它将是:
var result = news.NewsToPoliticians
.GroupJoin( db.Scores.Where(s= > s.IDNews == IDNews),
p => p.IDPolitician,
s => s.IDPolitician,
(k,g) => new
{
PoliticianId = k,
GroupedVotes = g.GroupBy(s => s.IDAtribute,
(id, group) => new
{
Atribute = id,
TotalScore = group.Sum(x => x.Score)
})
})
.ToList();
但是,您的提供商将如何对其进行翻译,以便它可能仍然是多个查询以解决此问题,您可以使用以下内容:
var politicianIds = news.NewsToPoliticians.Select(p => p.IDPolitician).ToList()
var result = db.Scores.Where(s= > s.IDNews == IDNews)
.Where(s => politicianIds.Contains(s.IDPolitician))
.GroupBy(p => p.IDPolitician,
(k,g) => new
{
PoliticianId = k,
GroupedVotes = g.GroupBy(s => s.IDAtribute,
(id, group) => new
{
Atribute = id,
TotalScore = group.Sum(x => x.Score)
})
})
.ToList();
希望最多2个查询(取决于NewsToPoliticians
是否依赖于数据库)。你只需要尝试一下然后看看。
答案 1 :(得分:1)
使用存储过程并让SQL服务器引擎完成所有工作。您仍然可以使用Linq来调用存储过程,这将最大限度地减少对数据库的所有调用