LINQ को ज्वाइन कैसे करना है एक सिंगल में कई फील्ड पर


244

मुझे एक LINQ2DataSet क्वेरी करने की ज़रूरत है जो एक से अधिक फ़ील्ड (जैसे) पर जुड़ती है

var result = from x in entity
join y in entity2 
       on x.field1 = y.field1 
and 
          x.field2 = y.field2

मुझे अभी तक एक उपयुक्त समाधान मिल गया है (मैं अतिरिक्त बाधाओं को एक खंड में जोड़ सकता हूं, लेकिन यह एक उपयुक्त समाधान से बहुत दूर है, या इस समाधान का उपयोग करें , लेकिन यह एक समान मानता है)।

क्या LINQ में कई फील्ड्स पर एक ही जॉइन करना संभव है?

संपादित करें

var result = from x in entity
             join y in entity2
             on new { x.field1, x.field2 } equals new { y.field1, y.field2 }

समाधान है जिसे मैंने ऊपर एक समभुज मानकर संदर्भित किया है।

आगे EDIT

आलोचना का जवाब देने के लिए कि मेरा मूल उदाहरण एक समरूप था, मैं इस बात को स्वीकार करता हूं कि, मेरी वर्तमान आवश्यकता एक समभुज के लिए है और मैंने पहले ही उल्लेखित समाधान को नियोजित कर दिया है।

हालांकि, मैं यह समझने की कोशिश कर रहा हूं कि मेरे पास LINQ के साथ क्या संभावनाएं और सर्वश्रेष्ठ प्रैक्टिस होनी चाहिए। मुझे जल्द ही एक टेबल आईडी के साथ डेट रेंज क्वैरी में शामिल होने की आवश्यकता है, और उस मुद्दे को पहले से ही खाली कर रहा था, ऐसा लगता है कि मुझे उस खंड में तारीख सीमा को जोड़ना होगा।

धन्यवाद, हमेशा की तरह, सभी सुझावों और टिप्पणियों के लिए


48
इसे पढ़ने वाले किसी भी व्यक्ति के लिए बस एक FYI करें, यदि आप annon कक्षाओं में एक मल्टी फील्ड जॉइन करते हैं, तो आप दोनों annon क्लासेस में फ़ील्ड्स को एक ही नाम दें, अन्यथा आपको कंपाइल एरर मिलते हैं।
मार्क

6
या इसके बजाय, आपको यह सुनिश्चित करना होगा कि उनके मिलान नाम हों। यानी आप उन्हें एक दूसरे से मिलाने के लिए सिर्फ एक प्रकार के एनॉन प्रकारों के नाम बता सकते हैं।
टॉम फर्ग्यूसन 14

1
इस उत्तर पर ध्यान दें stackoverflow.com/a/34176502/1704458
TS

मैंने वस्तुओं के बजाय बराबरी के दोनों ओर टुपल्स का इस्तेमाल किया और यह काम भी करने लगा।
GHZ

जवाबों:


89

अनाम प्रकार के साथ समाधान ठीक काम करना चाहिए। LINQ केवल इक्विजेंस का प्रतिनिधित्व कर सकता है (साथ में क्लॉस, वैसे भी), और वास्तव में यही आपने कहा है कि आप अपनी मूल क्वेरी के आधार पर वैसे भी व्यक्त करना चाहते हैं।

यदि आपको किसी विशेष कारण से अनाम प्रकार वाला संस्करण पसंद नहीं है, तो आपको उस कारण की व्याख्या करनी चाहिए।

यदि आप मूल रूप से आपके द्वारा मांगे जाने के अलावा कुछ करना चाहते हैं, तो कृपया एक उदाहरण दें कि आप वास्तव में क्या करना चाहते हैं।

संपादित करें: प्रश्न में संपादित करने के लिए प्रतिक्रिया: हां, "तिथि सीमा" में शामिल होने के लिए, आपको इसके बजाय एक खंड का उपयोग करने की आवश्यकता है। वे शब्दार्थ रूप से वास्तव में समतुल्य हैं, इसलिए यह अभी उपलब्ध अनुकूलन का मामला है। समीकरण सरल अनुक्रम प्रदान करते हैं (LINQ में ऑब्जेक्ट्स, जिसमें LINQ to DataSets शामिल है) आंतरिक अनुक्रम के आधार पर एक लुकअप बनाकर - इसे कुंजी से मिलान करने वाले प्रविष्टियों के अनुक्रम से कुंजी के रूप में एक हैशटेबल के रूप में सोचें।

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


धन्यवाद, हां प्रदर्शन जहां क्लॉज का उपयोग करने के साथ मेरी मुख्य चिंता है। मैं अनुमान लगा रहा हूं कि ज्वाइन के बाद एक क्लॉज एक बड़े डेटासेट पर एक फिल्टर करेगा जो दूसरे जॉइन पैरामीटर को शुरू करने से कम हो सकता है। मुझे टेस्ट करने के लिए ऑर्डर करने का विचार पसंद है अगर मुझे दक्षता प्राप्त हो सकती है
जॉन्स

आपके पास कितने रिकॉर्ड होंगे? यह मत भूलो कि परिणाम के साथ शुरू करने के लिए समय की एक निश्चित राशि के साथ शुरू करने के लिए ले जाएगा ...
जॉन स्कीट

"वे शब्दशः समतुल्य हैं वास्तव में" - क्या हमें वहां 'वास्तव में' शब्द की आवश्यकता है? शायद आपका मतलब था, "वे वास्तव में शब्दार्थ समतुल्य हैं" :)
onedaywhen

136
var result = from x in entity
   join y in entity2 on new { x.field1, x.field2 } equals new { y.field1, y.field2 }

यह वही है जिसे मैं देखने के लिए देख रहा था क्योंकि 101 Linq नमूने में यह नहीं था, या कम से कम जो मैंने देखा था।
क्रिस मैरिकिक

1
@PeterX वास्तव में यह कर सकता है, मेरा जवाब यहां देखें: stackoverflow.com/a/22176658/595157
niieani

13
उपरोक्त कोड काम नहीं किया। on new { X1= x.field1, X2= x.field2 } equals new { X1=y.field1, X2= y.field2 } इसे जोड़ने के बाद काम हुआ
रवि राम

@ रवि राम .. धन्यवाद .. आपकी टिप्पणी ने मदद की
NMathur

80
var result = from x in entity1
             join y in entity2
             on new { X1= x.field1, X2= x.field2 } equals new { X1=y.field1, X2= y.field2 }

आपको यह करने की आवश्यकता है, यदि स्तंभ नाम दो संस्थाओं में भिन्न हैं।


6
विभिन्न कॉलम नामों का उल्लेख करने के लिए धन्यवाद। इससे मेरी खराब अभिव्यक्ति ठीक हो गई।
Ga

1
इसने मेरे लिए भी काम किया। यदि कॉलम के नाम मेल नहीं खाते हैं, तो आपको यह त्रुटि मिलेगी, "ज्वाइन क्लॉज में किसी एक एक्सप्रेशन का प्रकार गलत है। 'GroupJoin' में कॉल में इंफेक्शन फेल है।"
हम्बड्स

मुख्य चर को अलियास करने के लिए धन्यवाद।
थॉमस.बेंज

मुझे वह त्रुटि मिली जिसका उल्लेख @humbads ने किया था जब मैंने int के सभी गुणों का नाम 'नया {}' नहीं रखा था। तो बस फी, अगर आप एक नाम रखते हैं तो आपको बाकी का नाम भी होना चाहिए।
ईथन मेल ने

आपको बहुत अच्छा लगता है
चार्ली एच

51

एक समतुल्य विधि श्रृंखला सिंटैक्स के साथ इसे पूरा करने के लिए:

entity.Join(entity2, x => new {x.Field1, x.Field2},
                     y => new {y.Field1, y.Field2}, (x, y) => x);

जबकि अंतिम तर्क (x, y) => xवह है जो आप चुनते हैं (उपरोक्त मामले में हम चुनते हैं x)।


31

मुझे लगता है कि कहां फ़ंक्शन का उपयोग करने के लिए एक अधिक पठनीय और लचीला विकल्प है:

var result = from x in entity1
             from y in entity2
                 .Where(y => y.field1 == x.field1 && y.field2 == x.field2)

यह आसानी से आंतरिक जोड़ से बाईं ओर जुड़ने की अनुमति देता है, इसे जोड़कर ।DefaultIfEmpty ()।


अब लंबे समय से लंबोदर उपयोगकर्ता के रूप में (जब मैंने सवाल पूछा तो विरोध किया), मुझे सहमत होना होगा
johnc

क्या यह धीमा होगा?
अल्फ्रेडब्र सिप

1
मुझे लगता है कि इसमें नए { ... } equals new { ... }सिंटैक्स के समान प्रदर्शन होना चाहिए । LinqPad यह देखने के लिए एक शानदार उपकरण है कि अभिव्यक्ति कैसे व्यवहार कर रही है (SQL स्क्रिप्ट अगर LINQ2SQL का उपयोग किया जाता है, अभिव्यक्ति के पेड़ आदि)
अलेक्सी

जहाँ तक मैंने देखा कि यह INNER JOIN
Mariusz

@ मर्सिज़ हां, यह इनसिन जॉइन के बजाय CROSS JOIN + को जनरेट करने के लिए समझ में आता है। सरल प्रश्नों के लिए, मुझे उम्मीद है कि विश्लेषक बहुत ही समान उत्पन्न करेंगे।
एलेक्सी

10
var result = from x in entity
             join y in entity2
             on new { X1= x.field1, X2= x.field2 } equals new { X1=y.field1, X2= y.field2 }
             select new 
             {
               /// Columns
              };

8

आप ऐसा कुछ कर सकते हैं (नीचे)

var query = from p in context.T1

        join q in context.T2

        on

        new { p.Col1, p.Col2 }

        equals

         new { q.Col1, q.Col2 }

        select new {p...., q......};

जैसा कि मैंने प्रश्न में उल्लेख किया है, इसके लिए एक समान की आवश्यकता है
जॉन्क

7

जॉइन ऑपरेटर का उपयोग करके आप केवल समरूप प्रदर्शन कर सकते हैं। अन्य ऑपरेटरों के उपयोग से अन्य प्रकार के निर्माण किए जा सकते हैं। मुझे यकीन नहीं है कि आप जो सटीक प्रयास कर रहे हैं वह इन तरीकों का उपयोग करके या जहां क्लॉज को बदलकर आसान होगा। ज्वाइन क्लॉज पर डॉक्यूमेंटेशन यहां पाया जा सकता है । MSDN में अन्य जॉइन के उदाहरणों के साथ कई लिंक के साथ जुड़ने के संचालन पर एक लेख है


3

यदि फ़ील्ड नाम संस्थाओं में भिन्न हैं

var result = from x in entity
   join y in entity2 on 
          new {
                field1=   x.field1,
               field2 =  x.field2 
             } 
          equals
         new { 
                field1= y.field1,
                field2=  y.myfield
              }
select new {x,y});

धन्यवाद। नाम मिलान वह टुकड़ा था जो मुझे याद आ रहा था।
ब्रेट

2

एक पूर्ण विधि श्रृंखला के रूप में जो इस तरह दिखेगा:

lista.SelectMany(a => listb.Where(xi => b.Id == a.Id && b.Total != a.Total),
                (a, b) => new ResultItem
                {
                    Id = a.Id,
                    ATotal = a.Total,
                    BTotal = b.Total
                }).ToList();

-2
from d in db.CourseDispatches
                             join du in db.DispatchUsers on d.id equals du.dispatch_id
                             join u in db.Users on du.user_id equals u.id
                             join fr in db.Forumreports on (d.course_id + '_' + du.user_id)  equals  (fr.course_id + '_'+ fr.uid)

यह मेरे लिए काम करता है


यह कई में शामिल होने के लिए, वह एक एक एकल में एक से अधिक क्षेत्रों के साथ शामिल होने के योग्य बनाना चाहता है में शामिल होने के
theLaw

-3

जिन तत्वों से आप जुड़ना चाहते हैं, उन्हें रखने के लिए एक वर्ग (प्रकार) घोषित करें। नीचे दिए गए उदाहरण में JoinElement की घोषणा करें

 public class **JoinElement**
{
    public int? Id { get; set; }
    public string Name { get; set; }

}

results = from course in courseQueryable.AsQueryable()
                  join agency in agencyQueryable.AsQueryable()
                   on new **JoinElement**() { Id = course.CourseAgencyId, Name = course.CourseDeveloper } 
                   equals new **JoinElement**() { Id = agency.CourseAgencyId, Name = "D" } into temp1

1
यह 9 साल पहले ही उत्तर दिया जा चुका है ... यह उत्तर क्या मूल्य लाता है?
Maciej Jureczko
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.