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 になります。

サンプルデータ:

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)

Product1: は 1 回だけリストする必要があります... 上記のコードは pastebin にあります:http://pastebin.com/cNHTBSie

ベストアンサー1

最初の「サンプルデータの結果」がどこから来ているのか分かりませんが、コンソールアプリの問題はSelectMany各グループの各項目

あなたが望んでいるのはただ次のことだと思います:

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();

ここで製品名を取得するためにを使用するFirst()と、同じ製品コードを持つすべての製品が同じ製品名を持つことが想定されます。コメントに記載されているように、製品名と製品コードでグループ化できます。これにより、特定のコードで名前が常に同じであれば同じ結果が得られますが、EF ではより優れた SQL が生成されるようです。

Quantityまた、およびプロパティをそれぞれおよびタイプPriceに変更することをお勧めします。明らかにテキストではないデータに文字列プロパティを使用するのはなぜでしょうか?intdecimal

おすすめ記事