2009-10-03 11 views
5

मैं वर्तमान में SQL सर्वर 2008 डेटाबेस से संग्रहीत प्रोसेस के माध्यम से आलेख ऑब्जेक्ट निकालने के लिए एक SQL डेटा रीडर (vb.net में) का उपयोग कर रहा हूं। इस वस्तु का एक हिस्सा नीचे दिखाया गया है दो गुण शामिल हैं:यदि मूल्य शून्य है तो मैं एक sqldatareader को मान कैसे वापस कर सकता हूं?

theArticle.Truthfulness = ((myReader.GetInt32(myReader.GetOrdinal("Truthfulness")))) 
theArticle.Relevance = ((myReader.GetInt32(myReader.GetOrdinal("Relevance")))) 

मेरे समस्या यह है कि सच्चाई और प्रासंगिकता का तात्पर्य शून्य मान वापस आ सकते हैं और इस समारोह की गिरावट खड़ी कर रहा है है।

मुझे लगता है कि मैं समझता हूं क्यों। मैं एक पूर्णांक मान (getin32) के लिए पूछ रहा हूं और क्योंकि शून्य वापस आ गया है यह विफल रहता है।

मैं डेटाबेस से शून्य मान को कैसे समायोजित करूं ताकि यह खत्म न हो?

उत्तर

16

आप देख सकते हैं कि दी गई क्रमिक स्थिति .IsDBNull() का उपयोग कर शून्य है या फिर कुछ करें - उदा। -1 या कुछ और करने के लिए अपने मान सेट:

int myOrdinal = myReader.GetOrdinal("Truthfullness"); 

if(myReader.IsDBNull(myOrdinal)) 
{ 
    theArticle.Truthfulness = -1; 
} 
else 
{ 
    theArticle.Truthfulness = myReader.GetInt32(myOrdinal); 
} 

माइक होफ़र उसके जवाब में बताते हैं के रूप में, आप भी एक विस्तार विधि में यह सब तर्क लपेट सकता है:

public static class SqlDataReaderExtensions 
{ 
    public static int SafeGetInt32(this SqlDataReader reader, 
            string columnName, int defaultValue) 
    { 
     int ordinal = reader.GetOrdinal(columnName); 

     if(!reader.IsDbNull(ordinal)) 
     { 
      return reader.GetInt32(ordinal); 
     } 
     else 
     { 
      return defaultValue; 
     } 
    } 
} 

और उसके बाद सिर्फ इतना है कि "का उपयोग SafeGetInt32 "के बजाय विधि:

theArticle.Truthfulness = myReader.SafeGetInt32("Truthfullness", -1); 

मार्क

+0

या अपवाद को पकड़ें और इसके साथ सौदा करें – Mark

+1

हां, आप भी ऐसा कर सकते हैं - लेकिन अपवाद से बचने के लिए एक (सामान्य रूप से) –

+1

@marc_s को पकड़ने और संभालने से बेहतर है: मेरे उत्तर पर आपकी टिप्पणी से सहमत। इसे हटाना इसे स्पष्ट करने के लिए धन्यवाद। आपकी टिप्पणी थी "मैं यह काम नहीं करूँगा, क्योंकि डीबी कॉलम न्यूल है, इसलिए .GetInt32() कॉल अपवाद के साथ विफल हो जाएगी - आपको एक पूर्ण मूल्य वापस नहीं मिलेगा जिसे आप" ?? "ऑपरेटर ...." – Mahin

3

आप की जाँच की थी, SqlDataReader.IsDBNul एल विधि? शायद कुछ की तरह:

if(myReader.IsDBNull(myReader.GetOrdinal("Truthfulness")) 
theArticle.Truthfulness = string.Empty; 
else 
theArticle.Truthfulness = ((myReader.GetInt32(myReader.GetOrdinal("Truthfulness")))) 
+0

अच्छी तरह से, स्ट्रिंग। यदि आप int32 प्रॉपर्टी से निपट रहे हैं तो लक्षण बहुत अच्छा नहीं होगा ...... –

1

तुम्हें पता है, मैं Oracle में यह सब समय के साथ सौदा।

using System.Data.OracleClient; 
public static class OracleDataReaderExtensions 
{ 
    public static int GetInt32(this OracleDataReader reader, string columnName, int defaultValue) 
    { 
     return reader.GetInt32(reader.GetOrdinal(columnName)) != DbNull.Value ? 
       reader.GetInt32(reader.GetOrdinal(columnName)) : 
       defaultValue; 
    } 
} 

प्रत्येक प्रकार वापस करना चाहते के लिए एक अलग अधिभार बनाएँ: कोड को साफ करने के लिए, मैं आपरेशन को आसान बनाने के विस्तार के तरीकों का एक सेट लिखा था। मैं मुख्य रूप से स्ट्रिंग, int, दिनांक, और दशमलव के साथ काम करता हूं। YAGNI याद रखें (आप केवल उन आप वास्तव में उपयोग करते हैं, पाठक द्वारा समर्थित हर प्रकार के साथ काम करने की जरूरत नहीं है।)

एसक्यूएल सर्वर के लिए इस तरह का विस्तार वर्ग वास्तव में लिखने के लिए आसान है, और बेहद अपने काम को आसान बनाने में होगा। उस पर मेरा विश्वास करो। क्या मैं आपसे झूठ बोलूंगा? :)

+1

मुझे नहीं लगता कि यह काम करेगा, क्योंकि कॉलम डेटाबेस में पूर्ण है, तो GetInt32() को कॉल अपवाद का कारण बन जाएगा। आप DINull.Value के खिलाफ GetInt32() कॉल की तुलना नहीं कर सकते हैं और उस पर प्रतिक्रिया दें .... –

+0

असल में, यह काम करता है। मेरे द्वारा इसे हर दिन उपयोग किया जाता है। –

+0

इसका कारण यह है कि हम शॉर्ट सर्किटिंग का उपयोग कर रहे हैं?: ऑपरेटर। यदि यह शून्य नहीं है, तो हम इसे वापस कर देते हैं। अन्यथा, हम डिफ़ॉल्ट मान वापस करते हैं। –

0

यहाँ हम क्या SQLServer पर उपयोग है और यह एक आकर्षण की तरह काम करता है:

... 

    Dim X as Object = pbDr("TotAmt") 'dr is dim'ed as a DataReader 

... 

    Public Function pbDr(ByVal drName As String) As Object 

    Dim SQLError As SqlClient.SqlException 

    Dim IsNull As Boolean 

    Dim Ordinal, DispNbr As Integer 

    Try 
     Ordinal = dr.GetOrdinal(drName) 
     IsNull = dr.IsDBNull(Ordinal) 
     If IsNull Then 
     Dim Dbtype As String = dr.GetFieldType(Ordinal).ToString 
     If Dbtype = "System.String" Then 
      Return "" 
     ElseIf Dbtype = "System.Int32" _ 
     OrElse Dbtype = "System.Double" _ 
     OrElse Dbtype = "System.Decimal" _ 
     OrElse Dbtype = "System.Int16" Then 
      Return 0 
     Else 
      MsgBox("Print This Screen And Send To Support" _ 
      & "pbdr-Object = " & Dbtype, MsgBoxStyle.Critical) 
      Return "" 
     End If 
     Else 
     Return dr(Ordinal) 
     End If 

    Catch sqlerror 
     Call DispSQLError(SQLError, "pbDr") 
     pbDr = "" 
    End Try 

    End Function 
0

IsDbNull (int) आम तौर पर बहुत धीमी है कि यह है GetSqlInt32 तरह तरीकों का उपयोग कर और फिर DBNull.Value की तुलना में या उपयोग कर रहा है स्वयं ISNull Like:

public static int Int32(this SqlDataReader r, int ord) 
    { 
     var t = r.GetSqlInt32(ord); 
     return t.IsNull ? default(int) : t.Value; 
    } 

कुछ टेम्पलेट समाधानों का प्रयास किया लेकिन अब तक कोई फायदा नहीं हुआ। समस्या यह है कि सभी एसक्यूएल-प्रकार (SqlInt32 यहां) प्रकार वास्तव में structs हैं और जब वे सभी हैं। वैल्यू प्रॉपर्टी सी # में इसे संभालने के लिए वास्तविक टेम्पलेट्स नहीं हैं। इसके अलावा उनके पास अपना खुद का इन्सुलेबल इंटरफ़ेस है जो केवल IsNull है और Nyllable <> के साथ संगत नहीं है।

मुझे संदेह है कि किसी को एसक्यूएल प्रकारों के पूर्ण सेट को सी # टेम्पलेट्स के रूप में या केवल एक या दो टेम्पलेटेड विधियों में सक्षम होने के लिए ICOnvertible जोड़ने की आवश्यकता होगी।

कोई हो सकता है एक कार्यात्मक चाल या दो के साथ एक विचार है तो बोलो :-)

1

यह जेनेरिक वर्जन काम का हो सकता है:

private T ValueOrDefault<T>(System.Data.IDataReader rdr, string columnName) 
    { 
     T vod = default(T); 
     try 
     { 
      int idx = rdr.GetOrdinal(columnName); 
      if (!rdr.IsDBNull(idx)) 
       return (T)rdr[idx]; 
     } 
     catch (IndexOutOfRangeException) { } 

     return vod; 
    } 

InvalidCastException पकड़ने, या रूपांतरण का उपयोग करने के लिए बढ़ाया जा सकता है कास्टिंग के बजाय। श्रेणी टाइप?

+0

मुझे इंडेक्सऑटऑफेंजेंज अपवाद कैप्चर स्टेटमेंट को छोड़कर इस विकल्प को पसंद है। मुझे लगता है कि यदि आप अपने सिस्टम के अन्य हिस्सों में डिफ़ॉल्ट मानों को धक्का देने के बजाय स्कीमा संरचना बदल गई हैं, तो आप जितनी जल्दी हो सके जानना चाहेंगे। –

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

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