2016-08-19 10 views
13

मुझे यह जांचने की ज़रूरत है कि सभी परिभाषाओं में कुछ विशिष्ट डेटा है या नहीं। यह उस मामले को छोड़कर ठीक काम करता है जब ग्रुपबी खाली संग्रह देता है।लिंक सभी खाली संग्रह पर

var exist = dbContext.Definitions 
        .Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId) 
        .GroupBy(x => x.PropertyTypeId) 
        .All(...some condition...); 

इसे फिर से लिखने के लिए कैसे सभी खाली संग्रह पर झूठी वापसी करेंगे?

अद्यतन: यह एसक्यूएल के लिए एक LINQ है और मैं इसे एकल कॉल में निष्पादित करना चाहता था।

UPDATE2: मैं इस काम करता है लगता है:

var exist = dbContext.Definitions 
        .Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId) 
        .GroupBy(x => x.PropertyTypeId) 
        .Count(x => x 
         .All(...some condition...)) == propertyTypeIds.Count; 
+0

क्या यह LINQ ऑब्जेक्ट्स या कुछ और है? जवाब मूल रूप से अलग हो सकते हैं। –

+0

AllOrDefault – elloco999

+1

का उपयोग करने का प्रयास करें 'सभी' खाली संग्रह पर झूठी वापसी नहीं करेंगे। यहां देखें: http://stackoverflow.com/questions/7884888/why-does-enumerable-all-return-true-for-an-empty-sequence – sr28

उत्तर

0

क्या अपना स्वयं का एक्सटेंशन विधि लिखने के बारे में?

public static bool NotEmptyAll<T>(
    this IEnumerable<T> collection, 
    Func<T, bool> predicate) 
{ 
    return collection != null 
     && collection.Any() 
     && collection.All(predicate); 
} 

तब की All

var exist = definitions.Where(
     x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId) 
     .GroupBy(x => x.PropertyTypeId) 
     .NotEmptyAll(
      ...some condition...)); 
+5

ध्यान दें कि यह दो बार क्वेरी निष्पादित करता है, जो एक बुरा विचार हो सकता है। –

+0

@JonSkeet चेतावनी के लिए धन्यवाद। लेकिन यह एकमात्र समाधान है जो मेरे दिमाग में आता है। चूंकि इसे 'एंटिटीफ्रेमवर्क' टैग नहीं किया गया है, मुझे लगता है कि आम तौर पर इसका अधिक खर्च नहीं करना चाहिए। –

+0

वैसे यह एक बार ऐसा करने के लिए दोगुना खर्च होगा ... यह भी काफी अनन्य है ... जैसे कोई नियमित LINQ ऑपरेटर नहीं है जो आईआईआरसी के एक से अधिक बार अपने इनपुट का मूल्यांकन करता है। –

1

खैर बजाय इसे कहते (मैं बहुत यकीन है कि आप इसे बेहतर नाम होगा), तो आपको दो चरणों में यह कर सकते हैं:

var definitions = definitions.Where(
        x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId) 
        .GroupBy(x => x.PropertyTypeId); 

var exist = definitions.Any() && definitions.All(...some condition...); 
+5

शून्यता जांच की कोई आवश्यकता नहीं है - लेकिन आपको यह पता होना चाहिए कि यह क्वेरी को दो बार निष्पादित करेगा। –

+2

यदि यह एंटीटी फ्रेमवर्क की तरह कुछ है, तो यह डेटाबेस के विरुद्ध 2 प्रश्नों को चलाने का कारण बन जाएगा। – DavidG

+0

सच है, यह दो बार क्वेरी निष्पादित करेगा। इसे इंगित करने के लिए धन्यवाद। – Fabjan

5

आप कर सकते हैं Aggregate का उपयोग करके ऐसा करने में सक्षम हो जाएं:

.Aggregate(new {exists = 0, matches = 0}, (a, g) => 
     new {exists = a.exists + 1, matches = a.matches + g > 10 ? 1 : 0}) 

और फिर सरल तर्क exists शून्य और उस exists और matches से अधिक एक ही मूल्य है यह है कि (यहाँ, g > 10 अपने परीक्षण है)।

यह पूरी क्वेरी को दो बार चलाने से बचाता है।

3

आप DefaultIfEmpty विस्तार विधि का इस्तेमाल करते हैं, और अपने some condition इतना है कि यह मूल्यांकन करता nullfalse को समायोजित कर सकते हैं।

var exist = definitions 
    .Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId) 
    .GroupBy(x => x.PropertyTypeId) 
    .DefaultIfEmpty() 
    .All(...some condition...)); 
+1

बहुत चालाक! दूसरे शब्दों में, 'सभी (g => g! = Null && (... कुछ शर्त ...)) '। '... कुछ शर्त ...' लिखा गया है, इस पर निर्भर करता है कि अतिरिक्त कोष्ठक की आवश्यकता नहीं हो सकती है। – devgeezer

1

संपादित करें: पहला उत्तर काम नहीं करेगा।

आप कुछ हद तक आपकी क्वेरी को पुनर्व्यवस्थित हैं, तो आप अपनी हालत बदले बिना DefaultIfEmpty उपयोग कर सकते हैं:

var exist = dbContext.Definitions 
        .Where(x => propertyTypeIds.Contains(x.PropertyTypeId) 
            && x.CountryId == countryId) 
        .GroupBy(x => x.PropertyTypeId); 

      // apply the condition to all entries, 
      // resulting in sequence of bools (or empty), 
      // to permit the next step 
        .Select(...some condition...) 

      //if seq is empty, add `false` 
        .DefaultIfEmpty(false) 

      //All with identity function to apply the query and calculate result 
        .All(b => b) 
     ); 
+1

किसी टिप्पणी को चोरी करने के लिए एक हटाए गए उत्तर को खोलने के लिए (जिसे आप नहीं देख सकते): "लेकिन फिर आपको किसी से परिणाम प्राप्त करने की आवश्यकता है, जैसा कि सभी से प्राप्त किया जा रहा था (सच है अगर यह सभी के लिए सच है, अन्यथा झूठा) और आप एक ही स्थिति में वापस आ गए हैं " – DavidG

+0

@ डेविड जी डॉन, यह सही है। – RoadieRich

+0

@ डेविड जी नया संस्करण बेहतर है? – RoadieRich

12

आप वस्तुओं को LINQ उपयोग कर रहे हैं, मैं बस अपना खुद का विस्तार विधि लिखना चाहते हैं।

public static bool AnyAndAll<TSource>(
    this IEnumerable<TSource> source, 
    Func<TSource, bool> predicate) 
{ 
    if (source == null) 
    { 
     throw new ArgumentNullException(nameof(source)); 
    } 
    if (predicate == null) 
    { 
     throw new ArgumentNullException(nameof(predicate)); 
    } 

    bool any = false; 
    foreach (TSource item in source) 
    { 
     any = true; 
     if (!predicate(item)) 
     { 
      return false; 
     } 
    } 
    return any; 
} 

इस इनपुट एक बार से अधिक का मूल्यांकन टाल: मेरी Edulinq projectAll के लिए नमूना कोड है, और अनुकूल है कि बहुत सरल है।

0

यहाँ एक और चाल है:

var exist = dbContext.Definitions 
    .Where(x => propertyTypeIds.Contains(x.PropertyTypeId) && x.CountryId == countryId) 
    .GroupBy(x => x.PropertyTypeId) 
    .Min(some_condition ? (int?)1 : 0) == 1; 

यह इस तथ्य का इस्तेमाल करता है कि ऊपर Min<int?> विधि रिटर्न:

(ए) null जब सेट खाली है
(बी) 0 अगर कुछ तत्व
(सी) 1 के लिए स्थिति संतुष्ट नहीं है अगर स्थिति सभी तत्वों के लिए संतुष्ट है

इसलिए हम निरर्थक मूल्य तुलना नियमों का उपयोग करके (सी) के परिणाम को सरल जांचते हैं।

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