2012-05-08 12 views
6

मैं अपनी टेबल के लिए कई से अधिक रिश्तों का उपयोग करता हूं।LINQ कई से अधिक रिश्तों, एक सही WHERE खंड कैसे लिखना है?

var query = from post in context.Posts 
     from tag in post.Tags where tag.TagId == 10 
     select post; 

ठीक है, यह ठीक काम करता है:

एक प्रश्न नहीं है। मुझे आईडी द्वारा निर्दिष्ट टैग वाले पोस्ट मिलते हैं।

मेरे पास टैग आईडी का संग्रह है। और मैं अपने संग्रह में प्रत्येक टैग वाले पोस्ट प्राप्त करना चाहता हूं।

var tagIds = new int[]{1, 3, 7, 23, 56}; 

var query = from post in context.Posts 
     from tag in post.Tags where tagIds.Contains(tag.TagId) 
     select post; 

यह काम नहीं करता है:

मैं निम्नलिखित तरीके से प्रयास करें। क्वेरी निर्दिष्ट टैगों में से किसी एक को पोस्ट करने वाली सभी पोस्ट लौटाती है।

मैं इस तरह के एक खंड लेकिन dynamicaly संग्रह में से किसी टैग को गिनती के लिए प्राप्त करना चाहते हैं:

post.Tags.Whare(x => x.TagId = 1 && x.TagId = 3 && x.TagId = 7 && ...) 
+1

संभव डुप्लिकेट linq में आपूर्ति टैग?] (http://stackoverflow.com/questions/3478874/how-do-i-retrieve-items-that-are-tagged-with-all-the-supplied-tags-in-linq) –

उत्तर

24

आप बाहरी क्वेरी में प्रत्येक पोस्ट के टैग परियोजना नहीं होनी चाहिए; बल्कि, आपको एक आंतरिक क्वेरी का उपयोग करने की आवश्यकता है जो बाहरी फ़िल्टर के लिए चेक करता है। (एसक्यूएल में, हम यह एक correlated subquery कहते थे।)

var query = 
    from post in context.Posts 
    where post.Tags.All(tag => tagIds.Contains(tag.TagId)) 
    select post; 

वैकल्पिक वाक्य रचना:

var query = 
    context.Posts.Where(post => 
     post.Tags.All(tag => 
      tagIds.Contains(tag.TagId))); 

संपादित: Slauma’s clarification प्रति ठीक। नीचे दिया गया संस्करण उन पदों को लौटाता है जिनमें कम से कम tagIds संग्रह में सभी टैग शामिल हैं।

var query = 
    from post in context.Posts 
    where tagIds.All(requiredId => post.Tags.Any(tag => tag.TagId == requiredId)) 
    select post; 

वैकल्पिक वाक्य रचना:

var query = 
    context.Posts.Where(post => 
     tagIds.All(requiredId => 
      post.Tags.Any(tag => 
       tag.TagId == requiredId))); 

संपादित: Slauma प्रति ऊपर सही किया।

// Project posts from context for which 
// no Ids from tagIds are not matched 
// by any tags from post 
var query = 
    from post in context.Posts 
    where 
    ( 
     // Project Ids from tagIds that are 
     // not matched by any tags from post 
     from requiredId in tagIds 
     where 
     (
      // Project tags from post that match requiredId 
      from tag in post.Tags 
      where tag.TagId == requiredId 
      select tag 
     ).Any() == false 
     select requiredId 
    ).Any() == false 
    select post; 

मैं .Any() == false का उपयोग किया है Transact-SQL में NOT EXISTS ऑपरेटर अनुकरण करने के लिए: इसके अलावा एक और विकल्प नीचे क्वेरी सिंटैक्स का पूरा उपयोग की जाए।

+2

+1 केवल एकमात्र ** सभी ** टैग आईडी से मेल खाता है, न केवल ** कोई ** – mattytommo

+0

@mattytommo क्या आप इसके बारे में निश्चित हैं? ऐसा लगता है कि वह सभी पदों को प्राप्त कर रहा है। संपादित करें: उन्होंने अभी पोस्ट को जोड़ा। टैग्स। सभी ब्लॉक जो चाल चलाना चाहिए, लेकिन तेजों ने पहले ऐसा किया था। – Trisped

+0

@ ट्रिस्ड, कोई भी मेल नहीं खाता ** सभी ** आईडी टैग की सूची में है, न केवल ** कोई ** – mattytommo

4

यह वास्तव में बहुत आसान है:

var tags = context.Posts.Where(post => post.Tags.All(tag => tagIds.Contains(tag))); 
+0

वह ** सभी ** से मेल खाता है, न केवल 1 – mattytommo

+0

अपडेट किया गया है, फिर बस 'ऑल' एक्सटेंशन का उपयोग करके अपडेट किया गया। – Tejs

+0

यह पोस्ट वापस करेगा जहां * सभी * टैग टैग आईडी सूची में होते हैं। उदाहरण के लिए: tagIds = ("सी #", "जावा") और एक पोस्ट जिसमें केवल "सी #" टैग है। आपकी क्वेरी इस पोस्ट को वापस कर देगी। लेकिन वह चाहता है: "मेरे संग्रह में ** प्रत्येक टैग ** वाले पद प्राप्त करने के लिए"। I.e: केवल वे पोस्ट जिन्हें "सी #" ** और ** "जावा" के साथ टैग किया गया है। शायद, ऐसा करना इतना आसान नहीं है? :) – Slauma

0

Any साथ यह कोशिश करो।

var query = from post in context.Posts 
    from tag in post.Tags where tagIds.Any(t => t == tag.TagId) 
    select post; 
+0

वह ** ** ** से मेल खाता है, न केवल 1 – mattytommo

4

एक अन्य विकल्प दो सूचियों को विभाजित करने में अगर आप केवल करने के लिए टैग के संग्रह चाहते सेट आपके द्वारा निर्दिष्ट होते हैं और कोई अन्य है:

var query = from post in context.Posts 
    let tags = post.Tags.Select(x => x.Id).ToList() 
    where tags.Intersect(tagIds).Count() == tags.Length 
    select post; 
की [मैं आइटम है कि सभी के साथ टैग कर रहे हैं कैसे पुनः प्राप्त करते
+1

क्या आप 'टैग नहीं चाहते हैं। इंटरसेक्ट (टैग आईडी)। गणना() == टैग आईडी। लम्बाई '? – Trisped

+0

यह अच्छा लग रहा है! (@ ट्राइस्पेड की टिप्पणी में बदलाव के साथ) – Slauma

+0

@ ट्रिस्ड हां, मैंने जवाब – scottm

संबंधित मुद्दे