Linq: GroupBy, Sum and Count

后端 未结 3 2132
庸人自扰
庸人自扰 2020-11-22 15:45

I have a collection of products

public class Product {

   public Product() { }

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


        
相关标签:
3条回答
  • 2020-11-22 16:02

    The following query works. It uses each group to do the select instead of SelectMany. SelectMany works on each element from each collection. For example, in your query you have a result of 2 collections. SelectMany gets all the results, a total of 3, instead of each collection. The following code works on each IGrouping in the select portion to get your aggregate operations working correctly.

    var results = from line in Lines
                  group line by line.ProductCode into g
                  select new ResultLine {
                    ProductName = g.First().Name,
                    Price = g.Sum(pc => pc.Price).ToString(),
                    Quantity = g.Count().ToString(),
                  };
    
    0 讨论(0)
  • 2020-11-22 16:02

    sometimes you need to select some fields by FirstOrDefault() or singleOrDefault() you can use the below query:

    List<ResultLine> result = Lines
        .GroupBy(l => l.ProductCode)
        .Select(cl => new Models.ResultLine
                {
                    ProductName = cl.select(x=>x.Name).FirstOrDefault(),
                    Quantity = cl.Count().ToString(),
                    Price = cl.Sum(c => c.Price).ToString(),
                }).ToList();
    
    0 讨论(0)
  • I don't understand where the first "result with sample data" is coming from, but the problem in the console app is that you're using SelectMany to look at each item in each group.

    I think you just want:

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

    The use of First() here to get the product name assumes that every product with the same product code has the same product name. As noted in comments, you could group by product name as well as product code, which will give the same results if the name is always the same for any given code, but apparently generates better SQL in EF.

    I'd also suggest that you should change the Quantity and Price properties to be int and decimal types respectively - why use a string property for data which is clearly not textual?

    0 讨论(0)
提交回复
热议问题