Linq:GroupBy,Sum和Count

Linq:GroupBy,Sum和Count

我有一系列产品

public class Product {

   public Product() { }

   public string ProductCode {get; set;}
   public decimal Price {get; set; }
   public string Name {get; set;}}

现在,我想根据产品代码对集合进行分组,并返回一个对象,其中包含每个代码的名称,数量或产品以及每个产品的总价格。

public class ResultLine{

   public ResultLine() { }

   public string ProductName {get; set;}
   public string Price {get; set; }
   public string Quantity {get; set;}}

所以我使用GroupBy按ProductCode进行分组,然后计算总和并计算每个产品代码的记录数。

这是我到目前为止:

List<Product> Lines = LoadProducts();    List<ResultLine> result = Lines
                .GroupBy(l => l.ProductCode)
                .SelectMany(cl => cl.Select(
                    csLine => new ResultLine
                    {
                        ProductName =csLine.Name,
                        Quantity = cl.Count().ToString(),
                        Price = cl.Sum(c => c.Price).ToString(),
                    })).ToList<ResultLine>();

由于某种原因,总和正确完成但计数始终为1。

Sampe数据:

List<CartLine> Lines = new List<CartLine>();
            Lines.Add(new CartLine() { ProductCode = "p1", Price = 6.5M, Name = "Product1" });
            Lines.Add(new CartLine() { ProductCode = "p1", Price = 6.5M, Name = "Product1" });
            Lines.Add(new CartLine() { ProductCode = "p2", Price = 12M, Name = "Product2" });

样本数据的结果:

Product1: count 1   - Price:13 (2x6.5)Product2: count 1   - Price:12 (1x12)

产品1应该有count = 2!

我尝试在一个简单的控制台应用程序中模拟这个,但我得到以下结果:

Product1: count 2   - Price:13 (2x6.5)Product1: count 2   - Price:13 (2x6.5)Product2: count 1   - Price:12 (1x12)

产品1:应该只列出一次...上面的代码可以在pastebin上找到:http//pastebin.com/cNHTBSie


当年话下
浏览 1855回答 3
3回答

青春有我

我不明白第一个“带样本数据的结果”来自哪里,但控制台应用程序中的问题是您正在使用SelectMany查看每个组中的每个项目。我想你只想要:List<ResultLine>&nbsp;result&nbsp;=&nbsp;Lines &nbsp;&nbsp;&nbsp;&nbsp;.GroupBy(l&nbsp;=>&nbsp;l.ProductCode) &nbsp;&nbsp;&nbsp;&nbsp;.Select(cl&nbsp;=>&nbsp;new&nbsp;ResultLine &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProductName&nbsp;=&nbsp;cl.First().Name, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity&nbsp;=&nbsp;cl.Count().ToString(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Price&nbsp;=&nbsp;cl.Sum(c&nbsp;=>&nbsp;c.Price).ToString(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}).ToList();使用First()此处获取产品名称假设具有相同产品代码的每个产品具有相同的产品名称。如评论中所述,您可以按产品名称和产品代码进行分组,如果任何给定代码的名称始终相同,则会产生相同的结果,但显然会在EF中生成更好的SQL。我还建议你应该分别更改Quantity和Price属性int和decimal类型 - 为什么使用字符串属性显然不是文本的数据?

侃侃无极

以下查询有效。它使用每个组来进行选择而不是SelectMany。SelectMany适用于每个集合中的每个元素。例如,在您的查询中,您有2个集合的结果。SelectMany获得所有结果,总共3个,而不是每个集合。以下代码适用于IGrouping选择部分中的每个代码,以使您的聚合操作正常工作。var&nbsp;results&nbsp;=&nbsp;from&nbsp;line&nbsp;in&nbsp;Lines &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;group&nbsp;line&nbsp;by&nbsp;line.ProductCode&nbsp;into&nbsp;g&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select&nbsp;new&nbsp;ResultLine&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProductName&nbsp;=&nbsp;g.First().Name, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Price&nbsp;=&nbsp;g.Sum(_&nbsp;=>&nbsp;_.Price).ToString(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Quantity&nbsp;=&nbsp;g.Count().ToString(), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;};
打开App,查看更多内容
随时随地看视频慕课网APP