2009-08-17 16 views
12

के साथ शून्य परिणामों को संभालना मैं LINQ पर नया हूं और तालिका से ग्राफ़ में कुछ डेटा पॉइंट बनाने की कोशिश कर रहा हूं। इस तालिका में महत्व के तीन फ़ील्ड आईडी, समय और मूल्य हैं। मैं एक चुने हुए आईडी के लिए निर्धारित समय पर औसत मूल्य प्राप्त करने के लिए एक प्रश्न लिख रहा हूं। LINQ मैं लिखा है इस प्रकार है:LINQ औसत() विधि

var value = (from t in _table 
      where t.Id == id 
       && t.Time >= intervalStartTime 
       && t.Time <= intervalEndTime 
      select t.Value).Average(); 

हालांकि इस के साथ रनटाइम पर दुर्घटनाओं:

"शून्य मान प्रकार System.Decimal साथ एक सदस्य जो गैर-व्यर्थ है करने के लिए आवंटित नहीं किया जा सकता मान प्रकार .. "

निश्चित अंतराल पर कोई डेटा तो एसक्यूएल LINQ अशक्त रिटर्न, जो मैं 0 करने के लिए एकत्रित हो पसंद आया होगा उत्पन्न करता है, लेकिन इसके बजाय आवेदन दुर्घटनाओं है। क्या इस LINQ क्वेरी को सही तरीके से संभालने में सक्षम होने का कोई तरीका है?

[Serializable] 
[Table(Name = "ExampleTable")] 
public class ExampleTable 
{ 
    [Column(Name = "Id")] 
    public int Id { get; set; } 

    [Column(Name = "Time")] 
    public DateTime Time { get; set; } 

    [Column(Name = "Value")] 
    public int Value{ get; set; } 
} 

उत्तर

19

मुझे लगता है कि आप

var value = (from t in _table 
      where t.Id == id 
       && t.Time >= intervalStartTime 
       && t.Time <= intervalEndTime 
      select (int?)t.Value).Average() 

इस तरह चाहते हैं, तो आप एक double? वापस पाने, जबकि (int?) कलाकारों के बिना आप एक double वापस प्राप्त करने की आवश्यकता है, जो null नहीं हो सकता।

इस अशक्त के बजाय 0 के एक औसत प्राप्त करने के लिए हस्ताक्षर की वजह से है

double Enumerable.Average(IEnumerable<int> source) 
double? Enumerable.Average(IEnumerable<int?> source) 

अब, आप अंत

var value = (from t in _table 
      where t.Id == id 
       && t.Time >= intervalStartTime 
       && t.Time <= intervalEndTime 
      select (int?)t.Value).Average() ?? 0.0; 

IMHO पर कोलेसिंग ऑपरेटर रखने की आवश्यकता होगी यह Enumerable/Queryable वर्ग का एक बहुत भयानक डिज़ाइन है; Average(IEnumerable<int>) वापसी double? क्यों नहीं हो सकता है, केवल Average(IEnumerable<int?>) के लिए क्यों?

+0

धन्यवाद कि यह किया गया है। – Magpie

+0

सिर्फ इस मुद्दे में दूसरों की सहायता के लिए: यदि क्वेरी * कोई पंक्ति नहीं लौटाती है *, वास्तव में कुछ भी मदद नहीं करेगा। आपको सिर्फ क्वेरी को पूरी तरह से चलाने से बचना होगा। मुझे ऐसा अनुभव हुआ। – horace

+0

@horace: यह बस सच नहीं है। औसत, न्यूनतम, अधिकतम, क्वेरी सभी पंक्तियों से मेल नहीं खाती है जब तक कि कुल परिणाम शून्य न हो *। जैसा कि आप ऊपर दिए गए प्रश्न में देख सकते हैं, आपको कुल मिलाकर अभिव्यक्ति को लागू करने के लिए एक कास्ट की आवश्यकता होगी जब कुल अभिव्यक्ति एक शून्य प्रकार का नहीं है। (दुर्लभ मामले में यह अभी भी काम नहीं करता है, आप शायद एक flaky LINQ प्रदाता से निपट रहे हैं। यह LINQ की गलती नहीं है, और कोई प्रदाता मुझे पता है कि गड़बड़ है।) – Ruben

15

संपादित करें:

तालिका परिभाषा बातें स्पष्ट करने के लिए पूर्ण परिवर्तन :)

ठीक है, कैसे इस बारे में:

var value = (from t in _table 
      where t.Id == id 
       && t.Time >= intervalStartTime 
       && t.Time <= intervalEndTime 
      select t.Value).DefaultIfEmpty().Average() 

मुझे विश्वास है कि तार्किक क्या आप चाहते हैं - बदलना {} से {0}, इसलिए सभी औसत प्राप्त करने योग्य। मुझे नहीं पता कि यह एसक्यूएल के मामले में आप जो चाहते हैं वह करेंगे।

+0

क्षमा करें यह काम नहीं करता है क्योंकि मान एक गैर-शून्य है। – Magpie

+0

फिर 0 से "एम" को हटा दें और इसे ठीक काम करना चाहिए। –

+0

आह, मैं इस गलत तरीके से आ रहा हूं ... लटकाओ। –

1

संपादित करें: कुल Rework

मूल्य कास्टिंग कोशिश व्यर्थ करने के लिए पहले

var value = (from t in _table 
     where t.Id == id 
      && t.Time >= intervalStartTime 
      && t.Time <= intervalEndTime 
     select ((int?)t.Value) ?? 0).Average() 
+0

t.Value ?? 0 टी के रूप में संकलित नहीं है। वैल्यू एक गैर-शून्य int है। – Magpie

+0

क्या आपने इस संपादन को आजमाया है? इसका परिणाम क्या है? –

+0

हां, शिकायतकर्ता मुझे बताता है कि बाएं ऑपरेंड कभी भी शून्य नहीं होगा क्योंकि मान शून्य नहीं है – Magpie

0

निम्नलिखित का प्रयास करें। यह क्वेरी द्वारा लौटाई गई सभी शून्य वस्तुओं को छोड़ देगा।

var value = (from t in _table 
      where t != null 
      where t.Id == id 
       && t.Time >= intervalStartTime 
       && t.Time <= intervalEndTime 
      select t.Value).Average(); 

आप स्पष्ट रूप से शून्य के रूप में अशक्त आइटम के इलाज के लिए चाहते हैं, तो सशर्त ऑपरेटर का एक सरल उपयोग काम करना चाहिए:

var value = (from t in _table 
      where t == null || 
       (t.Id == id 
       && t.Time >= intervalStartTime 
       && t.Time <= intervalEndTime) 
      select t == null ? 0 : t.Value).Average(); 
+0

शून्य कैसे हो सकता है, और 'अंतराल स्टार्टटाइम' और 'अंतराल अंतराल' के बीच हो सकता है? मुझे लगता है कि उनकी समस्या यह है कि कुछ प्रारंभ और समाप्ति समय के बीच कोई रिकॉर्ड नहीं है, न कि तालिका में नल हैं। – Blorgbeard

+0

ओह, टी। वैल्यू बनाम टी। टाइम - मैं देखता हूं। – Blorgbeard

+0

सुझाव के लिए धन्यवाद लेकिन अभी भी एक ही अपवाद फेंकता है। – Magpie

0

आप प्रारंभिक क्वेरी के लिए एक अस्थायी का इस्तेमाल कर सकता ?

उदा:

var temp = (from t in _table 
      where t.Id == id 
       && t.Time >= intervalStartTime 
       && t.Time <= intervalEndTime 
      select t.Value) ?? new List<int>() {0}; 
var value = temp.Average(); 

सुनिश्चित नहीं हैं कि अगर यह मदद करता है।

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