在Linq中使用聚合的多个组

时间:2012-12-04 15:33:38

标签: c# sql linq sql-server-2008

我目前有这段代码:

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>

2 个答案:

答案 0 :(得分:2)

更新 - 由于用户注释已重新设置以尝试确保服务器上的聚合。 在这种情况下,我们可以通过IDPoliticianIDAttribute对服务器进行分组,然后在本地提取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来调用存储过程,这将最大限度地减少对数据库的所有调用