2011-08-22 14 views
13

से मेरे संग्रहीत प्रक्रिया परिणाम पढ़ने:अमान्य कलाकार अपवाद है जब SqlDataReader

@UserName nvarchar(64), 

    AS 

    BEGIN 
    SELECT MPU.UserName, SUM(TS.Monday)as Monday //TS.Monday contains float value 
    FROM dbo.MapTask MT JOIN dbo.MapPU MPU 
    ON MPU.ID = MT.MPUID 
    JOIN dbo.TimeSheet TS 
    ON MT.TMSID = TS.ID 
    WHERE MT.StartDate = @StartDate_int and MPU.UserName = @UserName 
    GROUP BY MPU.UserName 
    END 

मेरी सी # कोड में

SqlDataReader reader = command.ExecuteReader(); 

     while (reader.Read()) 
     { 
      float monday = (float)reader["Monday"]; // Invalid cast exception 
     } 

किसी मुझे बता सकते हैं कि मैं क्या गलत किया? धन्यवाद।

+0

आप Convert.ToFloat कोशिश कर सकते हैं (पाठक [ "सोमवार"] ToString()।); – Jethro

+0

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

+0

@ जोन स्कीट, जो समझ में आता है, साथ ही कनवर्ट करें। टोफ्लैट मौजूद नहीं है। अधिक सावधान रहना चाहिए। यदि कनवर्ट करें। टोफ्लैट मौजूद था तो यह करना बेहतर होगा। Convert.ToFloat (पाठक [ "सोमवार"]); ?? – Jethro

उत्तर

30

मेरा अनुमान है कि मूल्य float के बजाय बॉक्स किए गए double के रूप में वापस किया जा रहा है। जब आप इस प्रकार को अनबॉक्स करते हैं तो ठीक दाएं होना चाहिए। तो यह सोचते हैं मैं सही हूँ और यह decimal नहीं है या ऐसा ही कुछ है, तो आप इस्तेमाल कर सकते हैं:

float monday = (float) (double) reader["Monday"]; 

और यह काम करेगा। हालांकि यह बहुत बदसूरत है। यदि आप SqlDataReader.GetFloat का उपयोग करते हैं तो इसे पर प्राप्त करना चाहिए, यह वास्तव में एक एकल-सटीक मान है, और यह स्पष्ट है (आईएमओ) क्या हो रहा है।

दूसरी ओर, अपने डेटा वास्तव में एक double के रूप में डेटाबेस से वापस आ रहा हो सकता है, इस स्थिति में आप चाहिए (IMO) का उपयोग करें:

float monday = (float) reader.GetDouble(column); 

एक के रूप में अलग रूप में, आप यह सुनिश्चित करें कि कर रहे हैं float वास्तव में सबसे पहले यहां सबसे उपयुक्त प्रकार है? अक्सर decimal अधिक उपयुक्त है ...

+14

यदि SQL सर्वर में डेटाटाइप "फ्लोट" है, तो SqlDataReader.GetFloat को कॉल करना दुर्भाग्य से एक त्रुटि फेंक देगा, क्योंकि नामकरण सम्मेलन पूरी तरह से असंगत हैं। एक एसक्यूएल "फ्लोट" वास्तव में एक डबल-परिशुद्धता मान है और इसलिए एक .NET डबल पर मानचित्र करता है। एक एसक्यूएल "असली" एकल परिशुद्धता है जो एक .NET फ्लोट के लिए मानचित्र करता है। .NET के नाम आंतरिक रूप से असंगत हैं, कीवर्ड के रूप में "डबल" और "सिंगल" चुनने के बजाय, यह "फ्लोट" मिश्रण करता है, जबकि एसक्यूएल में यह "फ्लोट" और "असली" है जो डबल या सिंगल परिशुद्धता के संदर्भ में नहीं है। – Triynko

11

एक एसक्यूएल फ्लोट एक .NET डबल है, msdn पर देखें। डबल पर कास्टिंग करने का प्रयास करें।

+0

आप डबल करने के लिए और फिर फ्लोट करने का प्रयास कर सकते हैं, यही वह है जो मैं करता हूं। – TheGateKeeper

+0

यह सही उत्तर है। कास्ट अपवाद होता है क्योंकि SQL सर्वर क्रमशः डबल और एकल-परिशुद्धता मानों को संदर्भित करने के लिए "फ्लोट" और "असली" का उपयोग करता है। मुझे लगता है कि SqlDataReader को कॉल करने का प्रयास करना एक आम गलती है।एक SQL "फ्लोट" फ़ील्ड पर GetFloat, क्योंकि यह समझ में आता है, लेकिन हां, आपको SqlDataReader.GetDouble को कॉल करना होगा। और यदि आप एकल-परिशुद्धता मान को स्टोर करना चाहते हैं, तो यह "फ्लोट" से "असली" प्रकार को बदलने के लिए डेटाबेस पर वापस आ गया है। उन्हें बस "फ्लोट 32", "फ्लोट 64", "int32", int64 "के बजाय इस" छोटे "छोटे" "बड़े" "वास्तविक" "सिंगल" "डबल" बकवास के बजाय अटक जाना चाहिए था। – Triynko

1

मैं भी वही समस्या थी और यह कर समाप्त हो गया:

if (!oDR.IsDBNull(0)) 
    Rating = (float)oDR.GetSqlDecimal(0).Value; 

oDR.GetFloat (0) लौट रहा था और एक चयन औसत (...) का परिणाम तक पहुँचने जब अवैध डाली अपवाद

HTH

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