帮助以下linq查询?

时间:2010-03-03 15:24:36

标签: linq-to-sql

采取以下linq查询:

var summary = results.Select(r => 
                             new
                             {
                             TotalPopulation = results.Sum(s => s.Population),
                             TotalGross = results.Sum(s => s.Gross),
                             }).Distinct();

以上工作正常,但这是最好的方法。 r代表什么?我为什么需要它?

另外,我认为我可以在查询中添加以下内容,但我不能:

GrossPerPop = TotalPopulation / TotalGross

以上说在当前情况下不存在TotalPopulation和Total Gross。

我也尝试过:

GrossPerPop = results.sum(s => s.Population) / results.Sum(s => s.Gross), 

以上说/不能应用于小数?还是加倍?这与可空的字段有什么关系吗?碰巧我没有任何Population字段或具有空值的Gross字段,所以我将这些字段更改为sql表设计器中的非可空字段。但是,如果它们确实包含0值,我怎么能在Linq代码中检查它?

2 个答案:

答案 0 :(得分:3)

更好的方法是:

class Metrics {
    public int TotalPopulation { get; set; }
    public decimal TotalGross { get; set; }
    public decimal GrossPerPopulation {
        get {
            return TotalGross / TotalPopulation;
        }
    }
 }

然后:

var metrics = new Metrics {
                  TotalPopulation = results.Sum(s => s.Population), 
                  TotalGross = results.Sum(s => s.Gross)
              };

您目前所拥有的是为results的每个元素执行上述投影(尽管是匿名类型),然后抛弃除了一个结果投影之外的所有元素。你可以在不创建显式类型的情况下完成,就像我上面所做的那样,只使用匿名类型,但这很愚蠢。

  

r代表什么?

r表示您定义的匿名方法中的参数名称。

  

为什么需要它?

写作时

results.Select(expression)

expression必须是一个委托,它会占用results元素的任何类型,并返回其他类型。那是IEnumerable<SomeType>.Select用于将序列投射到另一个序列。因此,您必须传递一个方法,该方法会占用results元素的任何类型,并返回其他类型。一种方法是通过传递一个匿名委托。定义匿名委托的一种方法是使用lambda表达式。当你说r => ...时,你正在通过lambda表达式定义一个匿名方法。

  

另外,我认为我可以在查询中添加以下内容,但我不能:

     

GrossPerPop = TotalPopulation / TotalGross

没错,你做不到。想想这样。假设您有一个明确的类型

class Metrics {
    public int TotalPopulation { get; set; }
    public decimal TotalGross { get; set; }
    public decimal GrossPerPopulation { get; set; }
    public Metrics(
        int totalPopulation,
        decimal totalGross,
        decimal grossPerPopulation
    ) {
            TotalPopulation = totalPopulation;
            TotalGross = totalGross;
            GrossPerPopulation = grossPerPopulation;
    }
}

以下是否合法?

Metrics m = new Metrics(100, 100, m.TotalPopulation / m.TotalGross)

当然不是!但这实际上就是你要做的事情。

  

GrossPerPop = results.Sum(s => s.Population) / results.Sum(s => s.Gross)

     

以上说/不能应用于小数?还是加倍?

我认为你没有理由得到这样的信息。在C#中,上述内容是合法的,假设s.Populations.Gross都是数字类型;它们只会被隐含地提升为“正确”类型。即使s.Populations.Gross是数字类型,也是如此。

请注意,每人口总数应为

results.Sum(s => s.Gross) / results.Sum(s => s.Population)

答案 1 :(得分:2)

这不是一个好的查询,因为将为每一行计算Sum,然后它将是“不同的”。

只需写下

var summary = new
   {
      TotalPopulation = results.Sum(s => s.Population),
      TotalGross = results.Sum(s => s.Gross),
   };