3

假设我有这种假设的多对多关系:

public class Paper
{
  public int Id { get; set; }
  public string Title { get; set; }
  public virtual ICollection<Author> Authors { get; set; }
}

public class Author
{
  public int Id { get; set; }
  public string Name { get; set; }
  public virtual ICollection<Paper> Papers { get; set; }
}

我想使用 LINQ 构建一个查询,该查询将为我提供每位作者与其他作者相比的“受欢迎程度”,即作者贡献的论文数量除以所有论文中作者贡献的总数。我想出了几个查询来实现这一点。

选项1:

var query1 = from author in db.Authors
             let sum = (double)db.Authors.Sum(a => a.Papers.Count)
             select new
             {
               Author = author,
               Popularity = author.Papers.Count / sum
             };

选项 2:

var temp = db.Authors.Select(a => new
           {
             Auth = a,
             Contribs = a.Papers.Count
           });
var query2 = temp.Select(a => new
             {
               Author = a,
               Popularity = a.Contribs / (double)temp.Sum(a2 => a2.Contribs)
             });

基本上,我的问题是:其中哪个更有效,还有其他更有效的单个查询吗?其中任何一个如何与两个单独的查询进行比较,如下所示:

double sum = db.Authors.Sum(a => a.Papers.Count);
var query3 = from author in db.Authors
             select new
             {
               Author = author,
               Popularity = author.Papers.Count / sum
             };
4

2 回答 2

0

选项 1 和 2 应该生成相同的 SQL 代码。为了可读性,我会选择选项 1
选项 3 会生成两条 SQL 语句,速度会慢一些。

于 2013-02-21T08:43:26.523 回答
0

好吧,首先,您可以自己尝试一下,看看哪个耗时最长。

您应该寻找的第一件事是它们完美地转换为 SQL 或尽可能接近,以便数据不会全部加载到内存中只是为了应用这些计算。

但我觉得选项 2 可能是你最好的选择,还有一个优化来缓存贡献的页面总数。这样,您只需对数据库进行一次调用即可获取您无论如何需要的作者,其余的将在您的代码中运行,您可以在那里并行化并执行您需要的任何操作以使其快速运行。

所以是这样的(对不起,我更喜欢 Fluent 的 Linq 写作风格):

//here you can even load only the needed info if you don't need the whole entity.
//I imagine you might only need the name and the Pages.Count which you can use below, this would be another optimization.
var allAuthors = db.Authors.All(); 

var totalPageCount = allAuthors.Sum(x => x.Pages.Count);

var theEndResult = allAuthors .Select(a => new
         {
           Author = a,
           Popularity = a.Pages.Count/ (double)totalPageCount
         });
于 2013-02-21T07:54:24.970 回答