লিনক: গ্রুপ বাই, যোগফল এবং গণনা


133

আমার কাছে পণ্য সংগ্রহ রয়েছে

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

সুতরাং আমি প্রোডাক্ট কোড অনুসারে একটি গ্রুপবাই ব্যবহার করি, তারপরে আমি যোগফলটি গণনা করি এবং প্রতিটি পণ্য কোডের জন্য রেকর্ডের সংখ্যাও গণনা করি।

আমার এ পর্যন্ত যা আছে:

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 এর গণনা = 2 হওয়া উচিত!

আমি এটি একটি সাধারণ কনসোল অ্যাপ্লিকেশনটিতে অনুকরণ করার চেষ্টা করেছি কিন্তু সেখানে আমি নিম্নলিখিত ফলাফল পেয়েছি:

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

প্রোডাক্ট 1: কেবল একবার তালিকাভুক্ত করা উচিত ... উপরের কোডটি পেস্টবিনে পাওয়া যাবে: http://pastebin.com/cNHTBSie

উত্তর:


285

আমি বুঝতে পারি না যে "নমুনা ডেটা সহ প্রথম" ফলাফলটি কোথা থেকে এসেছে, তবে কনসোল অ্যাপ্লিকেশনে সমস্যা হ'ল আপনি প্রতিটি গ্রুপের প্রতিটি আইটেমটি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 এ আরও ভাল এসকিউএল উত্পন্ন করে।

আমি আপনাকে পরামর্শ দেব যে আপনার সম্পত্তি Quantityএবং Priceবৈশিষ্ট্যগুলি পরিবর্তন করা উচিতint এবং decimalধরনের যথাক্রমে - কেন তথ্য ব্যবহার করেন যা স্পষ্টভাবে পাঠগত নয় জন্য একটি স্ট্রিং সম্পত্তি?


ঠিক আছে আমার কনসোল অ্যাপটি কাজ করছে। আমাকে প্রথম () ব্যবহার করার জন্য এবং সিলেক্টম্যানি ছেড়ে দেওয়ার জন্য ধন্যবাদ। রেজাল্টলাইন আসলে একটি ভিউমোডেল। মূল্য মুদ্রার চিহ্ন সহ ফর্ম্যাট হবে। এজন্য আমার এটি স্ট্রিং হওয়া দরকার। তবে আমি পরিমাণ পরিবর্তন করতে পারলাম ইনট .. আমি এখন দেখব এটি আমার ওয়েবসাইটের জন্যও সহায়তা করতে পারে। আমি তোমাকে জানাবো.
ThdK

6
@ টিএইচডিকে: না, আপনাকেও Priceদশমিক হিসাবে রাখা উচিত এবং তারপরে আপনি কীভাবে এটি ফর্ম্যাট করবেন তা পরিবর্তন করা উচিত। ডেটা উপস্থাপনা পরিষ্কার রাখুন, এবং শুধুমাত্র শেষ সম্ভাব্য মুহুর্তে একটি উপস্থাপনা ভিউতে পরিবর্তন করুন।
জন স্কিটি

4
কেন প্রোডাক্ট কোড এবং নাম অনুসারে গ্রুপ করবেন না? এর মতো কিছু: .গ্রুপবি (l => নতুন {l.প্রডাক্টকোড, l.Name}) এবং প্রোডাক্টনাম = সি.কি.নেম ব্যবহার করুন
কিরিল বেস্তেমিয়ানভ

@ কিরিলবেস্টেমিয়ানভ: হ্যাঁ, এটি অবশ্যই অন্য একটি বিকল্প।
জন স্কিটি

ঠিক আছে, দেখে মনে হচ্ছে আমার সংগ্রহটি আসল সংগ্রহের চারপাশে একটি মোড়ক ছিল .. আমাকে গুলি করুন .. ভাল কথাটি হ'ল, আমি আজ কিছু লিঙ্ক অনুশীলন করেছি :)
থ্যাডকে

27

নিম্নলিখিত কোয়েরি কাজ করে। এটি প্রতিটি গ্রুপ পরিবর্তে নির্বাচন করতে ব্যবহার করে SelectManySelectManyপ্রতিটি সংগ্রহ থেকে প্রতিটি উপাদান নিয়ে কাজ করে। উদাহরণস্বরূপ, আপনার ক্যোয়ারিতে আপনার 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(pc => pc.Price).ToString(),
                Quantity = g.Count().ToString(),
              };

2

কখনও কখনও আপনার দ্বারা কিছু ক্ষেত্রগুলি নির্বাচন করতে হবে FirstOrDefault()বা singleOrDefault()আপনি নীচের কোয়েরিটি ব্যবহার করতে পারেন:

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

1
আপনি কি দয়া করে ব্যাখ্যা করতে পারেন কেন মাঝে মাঝে আমাকে FirstOrDefault() or সিঙ্গলঅরডিফল্ট () ব্যবহার করা প্রয়োজন ?
শান্তেশ্বর ইন্দে

@ শাশ্বেশ্বরআইন্ডে ফার্স্ট () এবং ফার্স্টঅরডিফল্ট () সিরিজের প্রথম অবজেক্ট পায়, যেখানে সিঙ্গেল () এবং সিঙ্গলঅরডেফল্ট () ফলাফল থেকে কেবল 1 টি প্রত্যাশা করে। যদি সিঙ্গেল () এবং সিঙ্গেলঅরডিফল্ট () দেখতে দেয় যে ফলাফলের সেটটিতে 1 বা একাধিক অবজেক্ট রয়েছে বা সরবরাহিত যুক্তির ফলস্বরূপ, এটি একটি ব্যতিক্রম ছুঁড়ে দেবে। আপনি যখন চান কেবল ব্যবহারের ক্ষেত্রে আপনি প্রাক্তনটি ব্যবহার করেন, সম্ভবত কোনও সিরিজ এবং অন্যান্য বস্তুর নমুনা আপনার পক্ষে গুরুত্বপূর্ণ নয়, আপনি যদি কেবলমাত্র একটি অবজেক্টের প্রত্যাশা করে থাকেন এবং যদি একাধিক ফলাফল থাকে তবে আপনি কিছু করেন তবে আপনি পরে ব্যবহার করেন যেমন লগ ত্রুটি।
ক্রিস্টিয়েন নেরোনা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.