2013-05-13 17 views
72

मैं उत्पादों की एक संग्रह हैLinq: GroupBy, योग और गणना

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;} 
} 

तो मैं ProductCode से समूह के लिए एक GroupBy उपयोग करते हैं, तो मैं योग की गणना और यह भी प्रत्येक उत्पाद कोड के लिए अभिलेखों की संख्या गिनती।

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 में गिनती = 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

उत्तर

167

मुझे समझ नहीं आता जहां पहले से आ रही है, लेकिन सांत्वना अनुप्रयोग में समस्या यह है कि आप 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() यहाँ के उपयोग के उत्पाद का नाम मानता है कि एक ही उत्पाद कोड के साथ हर उत्पाद एक ही उत्पाद नाम है पाने के लिए। जैसा कि टिप्पणियों में उल्लेख किया गया है, आप उत्पाद के नाम के साथ-साथ उत्पाद कोड द्वारा समूहित कर सकते हैं, जो किसी भी दिए गए कोड के लिए हमेशा समान होता है, लेकिन स्पष्ट रूप से ईएफ में बेहतर एसक्यूएल उत्पन्न करता है।

मैं भी सुझाव देंगे कि आप बदलना चाहिए Quantity और Price गुण int और decimal प्रकार क्रमश - क्यों डेटा है जो स्पष्ट रूप से शाब्दिक नहीं करने के लिए एक स्ट्रिंग संपत्ति का उपयोग करें?

+0

ठीक है मेरा कंसोल ऐप काम कर रहा है। पहले() का उपयोग करने के लिए मुझे इंगित करने के लिए धन्यवाद और SelectMany छोड़ दें। परिणाम रेखा वास्तव में एक व्यूमोडेल है।कीमत मुद्रा संकेत के साथ स्वरूपित हो जाएगी। यही कारण है कि मुझे इसे एक स्ट्रिंग होने की आवश्यकता है। लेकिन मैं मात्रा को int में बदल सकता हूं .. अब मैं देखूंगा कि यह मेरी वेबसाइट के लिए भी मदद कर सकता है। मैं आपको बता दूँगा। – ThdK

+5

@ThdK: नहीं, आपको 'प्राइस' को दशमलव के रूप में भी रखना चाहिए, और फिर इसे प्रारूपित करें कि आप इसे कैसे प्रारूपित करते हैं। डेटा प्रतिनिधित्व को साफ रखें, और अंतिम संभव पल में केवल प्रेजेंटेशन व्यू में बदलें। –

+4

क्यों उत्पाद कोड और नाम से समूह नहीं करना है? ऐसा कुछ: .GroupBy (l => नया {l.ProductCode, l.Name}) और ProductName = c.Key.Name, –

13

निम्न क्वेरी काम करता है। यह SelectMany के बजाय चयन करने के लिए प्रत्येक समूह का उपयोग करता है। SelectMany प्रत्येक संग्रह से प्रत्येक तत्व पर काम करता है। उदाहरण के लिए, आपकी क्वेरी में आपके पास 2 संग्रह का परिणाम है। SelectMany प्रत्येक संग्रह के बजाय, कुल परिणाम, कुल 3 प्राप्त करता है। निम्नलिखित कोड आपके समेकित संचालन को सही ढंग से काम करने के लिए प्रत्येक भाग में IGrouping पर काम करता है।

var results = from line in Lines 
       group line by line.ProductCode into g 
       select new ResultLine { 
       ProductName = g.First().Name, 
       Price = g.Sum(_ => _.Price).ToString(), 
       Quantity = g.Count().ToString(), 
       }; 
संबंधित मुद्दे