LINQ लैम्ब्डा में कई टेबल्स के बीच ज्वाइन कैसे करें


91

मैं LINQ में कई टेबलों के बीच में सम्मिलित होने की कोशिश कर रहा हूँ । मेरे पास निम्न वर्ग हैं:

Product {Id, ProdName, ProdQty}

Category {Id, CatName}

ProductCategory{ProdId, CatId} //association table

और मैं निम्नलिखित कोड का उपयोग करता हूं (जहां product, categoryऔर productcategoryउपरोक्त वर्गों के उदाहरण हैं):

var query = product.Join(productcategory, p => p.Id, pc => pc.ProdID, (p, pc) => new {product = p, productcategory = pc})
                   .Join(category, ppc => ppc.productcategory.CatId, c => c.Id, (ppc, c) => new { productproductcategory = ppc, category = c});

इस कोड के साथ मुझे निम्न वर्ग से एक वस्तु प्राप्त होती है:

QueryClass { productproductcategory, category}

जहां Productproductcategory प्रकार की है:

ProductProductCategoryClass {product, productcategory}

मुझे समझ नहीं आ रहा है कि "टेबल" में शामिल कहाँ है, मैं एक एकल वर्ग की उम्मीद कर रहा था जिसमें शामिल वर्गों से सभी गुण हैं।

मेरा उद्देश्य क्वेरी से उत्पन्न कुछ गुणों के साथ किसी अन्य ऑब्जेक्ट को आबाद करना है:

CategorizedProducts catProducts = query.Select(m => new { m.ProdId = ???, m.CatId = ???, //other assignments });

मैं यह लक्ष्य कैसे प्राप्त कर सकता हूं?


मुझे समझ नहीं आया ... क्यों m.ProdId = ??? के बजाय prodId = m.ProdId ?
एड्रियानो रेपेती

क्योंकि मुझे पहले से पता नहीं है कि प्रोडयूस को कैसे नेविगेट करना और प्राप्त करना है
CiccioMiami

जवाबों:


181

जुड़ने के लिए, मैं दृढ़ता से उन सभी विवरणों के लिए क्वेरी-सिंटैक्स पसंद करता हूं जो खुशी से छिपे हुए हैं (जिनमें से कम से कम पारदर्शी पहचानकर्ता शामिल नहीं हैं जो मध्यवर्ती अनुमानों के साथ शामिल हैं जो डॉट-सिंटैक्स समकक्ष में स्पष्ट हैं)। हालाँकि, आपने लम्बदा के बारे में पूछा, जो मुझे लगता है कि आपके पास वह सब कुछ है जो आपको चाहिए - आपको बस इसे एक साथ रखने की जरूरत है।

var categorizedProducts = product
    .Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc })
    .Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new { ppc, c })
    .Select(m => new { 
        ProdId = m.ppc.p.Id, // or m.ppc.pc.ProdId
        CatId = m.c.CatId
        // other assignments
    });

यदि आपको आवश्यकता है, तो आप स्थानीय चर में शामिल होने से बचा सकते हैं और बाद में इसका पुन: उपयोग कर सकते हैं, हालांकि इसके विपरीत अन्य विवरणों की कमी है, मुझे स्थानीय चर को पेश करने का कोई कारण नहीं दिखता है।

इसके अलावा, आप Selectदूसरे के अंतिम लैम्ब्डा में फेंक सकते हैं Join(फिर से, बशर्ते कि कोई अन्य ऑपरेशन नहीं हैं जो कि सम्मिलित परिणामों पर निर्भर हैं) जो देगा:

var categorizedProducts = product
    .Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc })
    .Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new {
        ProdId = ppc.p.Id, // or ppc.pc.ProdId
        CatId = c.CatId
        // other assignments
    });

... और क्वेरी सिंटैक्स पर आपको बेचने का अंतिम प्रयास करना, यह इस तरह दिखेगा:

var categorizedProducts =
    from p in product
    join pc in productcategory on p.Id equals pc.ProdId
    join c in category on pc.CatId equals c.Id
    select new {
        ProdId = p.Id, // or pc.ProdId
        CatId = c.CatId
        // other assignments
    };

आपके हाथ इस बात पर बंधे हो सकते हैं कि क्वेरी-सिंटैक्स उपलब्ध है या नहीं। मुझे पता है कि कुछ दुकानों में ऐसे जनादेश हैं - अक्सर इस धारणा पर आधारित है कि क्वेरी-सिंटैक्स कुछ हद तक डॉट-सिंटैक्स से सीमित है। अन्य कारण हैं, जैसे "अगर मैं डॉट-सिंटैक्स में सब कुछ और अधिक कर सकता हूं तो मुझे दूसरा सिंटैक्स क्यों सीखना चाहिए?" जैसा कि यह अंतिम भाग दिखाता है - ऐसे विवरण हैं जो क्वेरी-सिंटैक्स छुपाता है जो इसे पठनीयता में सुधार के साथ अच्छी तरह से गले लगाने लायक बना सकता है: उन सभी मध्यवर्ती अनुमानों और पहचानकर्ताओं जिन्हें आपको खाना बनाना है, खुशी से सामने-और-केंद्र नहीं हैं क्वेरी-सिंटैक्स संस्करण में चरण - वे पृष्ठभूमि फ़ुल हैं। अब मेरे साबुन-बॉक्स को बंद करें - किसी भी तरह, प्रश्न के लिए धन्यवाद। :)


3
धन्यवाद आपका समाधान अधिक पूर्ण है। मैं मानता हूं कि कुछ मामलों में क्वेरी सिंटैक्स अधिक स्पष्ट है लेकिन आपने सही अनुमान लगाया है, मुझे लैम्ब्डा का उपयोग करने के लिए कहा गया है। इसके अलावा मुझे 6 तालिकाओं में शामिल होना है, और इस मामले में डॉट नोटेशन अधिक साफ है
CiccioMiami

अगर हम JOINबयान में अतिरिक्त स्थिति की आवश्यकता है तो क्या ? हम यह कैसे करे? उदाहरण के लिए, join pc in productcategory on p.Id equals pc.ProdIdलाइन में, हमें जोड़ने की आवश्यकता है and p.Id == 1
हरमबे अटैक हेलीकॉप्टर

ऐसा लगता है कि आप चाहते हैं कि p.Id == 1चूंकि यह एक फिल्टर से कहीं ज्यादा है, जहां यह एक मानदंड है। जिस तरह से आप एक से अधिक मानदंडों पर शामिल होते हैं, आमतौर पर एक अनाम प्रकार का उपयोग करना होता है join pc in productcategory on new { Id = p.Id, Other = p.Other } equals new { Id = pc.ProdId, Other = pc.Other }:। यह Linq-to-Objects में काम करता है, और मुझे लगता है कि डेटाबेस प्रश्नों के साथ भी काम करेगा। डेटाबेस के साथ, आप विदेशी कुंजियों को उचित रूप में परिभाषित करने और संबंधित संपत्ति के माध्यम से संबंधित डेटा तक पहुँचने के द्वारा जटिल जुड़ाव प्रश्नों से गुजरने में सक्षम हो सकते हैं।
devgeezer

स्वच्छ समाधान के लिए धन्यवाद।
थॉमस.बेंज

आपके उदाहरण में: डॉट सिंटैक्स में, पीपीसी पीपीपीपी अनाम प्रकार सही हैं? क्वेरी सिंटैक्स में, अंतिम चयन में आपके द्वारा उपयोग किया जाने वाला p.id अभी भी एक उत्पाद वस्तु है क्या मैं सही हूं? तो यदि आप मिनियाबी जैसे अंतिम रिटर्निंग शेमा में ऑपरेशन करने के लिए कई तालिकाओं में शामिल होते हैं तो क्वेरी सिंटैक्स आसान है?
CDrosos

12

आपने जो देखा है वह वही है जो आपको मिलता है - और यह वही है जो आपने यहां मांगा था:

(ppc, c) => new { productproductcategory = ppc, category = c}

यह एक लंबोदर अभिव्यक्ति है जो उन दो गुणों के साथ एक अनाम प्रकार लौटाता है।

आपके वर्गीकृत उत्पाद में, आपको बस उन गुणों से गुजरना होगा:

CategorizedProducts catProducts = query.Select(
      m => new { 
             ProdId = m.productproductcategory.product.Id, 
             CatId = m.category.CatId, 
             // other assignments 
           });

धन्यवाद। मैं अनाम वर्ग के बारे में चर्चा को समझता हूं लेकिन इसके गुणों में क्वेरी को पूरा करने वाली कक्षा की वस्तुएं हैं? और क्या होता है जब मैं 2 जॉइन करता हूं? productproductcategory.product श्रेणी के अधिकार के साथ शामिल नहीं है?
CiccioMiami

@CiccioM मियामी: ठीक है, गुण वस्तुओं के संदर्भ में हैं, हाँ। यह वास्तव में स्पष्ट नहीं है कि आपके द्वारा "नहीं जुड़ने" का क्या मतलब है - आपको अपनी क्वेरी से क्या जानकारी नहीं मिलती है जो आप प्राप्त करना चाहते हैं?
जॉन स्कीट

पहली जॉइन के साथ मुझे प्रोडक्ट्स और प्रोडक्टश्रेरी के बीच का जुड़ाव मिलता है। दूसरे के साथ मुझे productcategory (सम्मिलित उत्पाद) और श्रेणी के बीच जुड़ना है। इसका अर्थ है कि एकाधिक शामिल होने के बारे में जानकारी केवल productproductcategory में निहित है। इसका मतलब यह है कि उत्पाद (और श्रेणी) सिर्फ उत्पाद श्रेणी के साथ जुड़ जाते हैं।
CiccioMiami 13

1
@CiccioM मियामी: क्षमा करें, मैं आपका अनुसरण नहीं कर रहा हूं - लेकिन यदि आप जुड़ने को निर्दिष्ट करते हैं, तो यह ऐसा करेगा। क्या आपने मेरे उत्तर में कोड का उपयोग करने की कोशिश की है ? क्या यह वह नहीं करता जो आप चाहते हैं?
जॉन स्कीट

क्षमा करें, मैं आपके कोड को प्राप्त करना चाहता था। काम का CatId काम ठीक है। इसके लिए OR ProdIdहोना चाहिए । दो असाइनमेंट अलग-अलग हैं, पहला उत्पाद पर है (साथ में ) और दूसरा दोनों के साथ शामिल है और । क्या आप मेरे तर्क का पालन करते हैं? m.productproductcategory.product.Idm.productproductcategory.productcategory.ProdIdproductcategoryproductcategoryproductcategory
CiccioM मियामी

5

मेरी परियोजना के इस नमूना कोड को देखें

public static IList<Letter> GetDepartmentLettersLinq(int departmentId)
{
    IEnumerable<Letter> allDepartmentLetters =
        from allLetter in LetterService.GetAllLetters()
        join allUser in UserService.GetAllUsers() on allLetter.EmployeeID equals allUser.ID into usersGroup
        from user in usersGroup.DefaultIfEmpty()// here is the tricky part
        join allDepartment in DepartmentService.GetAllDepartments() on user.DepartmentID equals allDepartment.ID
        where allDepartment.ID == departmentId
        select allLetter;

    return allDepartmentLetters.ToArray();
}

इस कोड में मैं 3 तालिकाओं में शामिल हुआ और मैंने उस खंड में शामिल होने की शर्त लगाई जहां से खंड

नोट: सेवा कक्षाएं डेटाबेस संचालन के लिए सिर्फ विकृत (गुप्त) हैं


2
 public ActionResult Index()
    {
        List<CustomerOrder_Result> obj = new List<CustomerOrder_Result>();

       var  orderlist = (from a in db.OrderMasters
                         join b in db.Customers on a.CustomerId equals b.Id
                         join c in db.CustomerAddresses on b.Id equals c.CustomerId
                         where a.Status == "Pending"
                         select new
                         {
                             Customername = b.Customername,
                             Phone = b.Phone,
                             OrderId = a.OrderId,
                             OrderDate = a.OrderDate,
                             NoOfItems = a.NoOfItems,
                             Order_amt = a.Order_amt,
                             dis_amt = a.Dis_amt,
                             net_amt = a.Net_amt,
                             status=a.Status,  
                             address = c.address,
                             City = c.City,
                             State = c.State,
                             Pin = c.Pin

                         }) ;
       foreach (var item in orderlist)
       {

           CustomerOrder_Result clr = new CustomerOrder_Result();
           clr.Customername=item.Customername;
           clr.Phone = item.Phone;
           clr.OrderId = item.OrderId;
           clr.OrderDate = item.OrderDate;
           clr.NoOfItems = item.NoOfItems;
           clr.Order_amt = item.Order_amt;
           clr.net_amt = item.net_amt;
           clr.address = item.address;
           clr.City = item.City;
           clr.State = item.State;
           clr.Pin = item.Pin;
           clr.status = item.status;

           obj.Add(clr);



       }

1
हालांकि यह कोड स्निपेट प्रश्न को हल कर सकता है, जिसमें स्पष्टीकरण सहित वास्तव में आपकी पोस्ट की गुणवत्ता में सुधार करने में मदद करता है। याद रखें कि आप भविष्य में पाठकों के लिए प्रश्न का उत्तर दे रहे हैं, और वे लोग आपके कोड सुझाव के कारणों को नहीं जान सकते हैं।
डॉ। रॉब लैंग

0
var query = from a in d.tbl_Usuarios
                    from b in d.tblComidaPreferidas
                    from c in d.tblLugarNacimientoes
                    select new
                    {
                        _nombre = a.Nombre,
                        _comida = b.ComidaPreferida,
                        _lNacimiento = c.Ciudad
                    };
        foreach (var i in query)
        {
            Console.WriteLine($"{i._nombre } le gusta {i._comida} y nació en {i._lNacimiento}");
        }

बस इतना आसान है, लेकिन लैंबडा ऍक्स्प के साथ बेहतर है जैसे कुछ लोगों ने कहा।
एलेक्स मार्टिनेज़

0

यह एक समय हो गया है लेकिन मेरा जवाब किसी की मदद कर सकता है:

यदि आप पहले से ही संबंध को ठीक से परिभाषित करते हैं तो आप इसका उपयोग कर सकते हैं:

        var res = query.Products.Select(m => new
        {
            productID = product.Id,
            categoryID = m.ProductCategory.Select(s => s.Category.ID).ToList(),
        }).ToList();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.