'System.String` टाइप करने के लिए' System.DBNull 'प्रकार की ऑब्जेक्ट कास्ट करने में असमर्थ


109

मुझे अपने ऐप में उपरोक्त त्रुटि मिली। यहाँ मूल कोड है

public string GetCustomerNumber(Guid id)
{
     string accountNumber = 
          (string)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidmyApp, 
                          CommandType.StoredProcedure, 
                          "GetCustomerNumber", 
                          new SqlParameter("@id", id));
     return accountNumber.ToString();
 }

मैंने साथ दिया

public string GetCustomerNumber(Guid id)
{
   object accountNumber =  
          (object)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidCRM, 
                                CommandType.StoredProcedure, 
                                "spx_GetCustomerNumber", 
                                new SqlParameter("@id", id));
    if (accountNumber is System.DBNull)
    {
       return string.Empty;
    }
    else
    {
       return accountNumber.ToString();
    }
}

क्या इसके आसपास एक बेहतर तरीका है?


2
आपको वास्तव में @ लगाम के जवाब में देखना चाहिए, आपको लंबे समय में बहुत समय बचाएगा
रोमन एम

जवाबों:


90

एक छोटे रूप का उपयोग किया जा सकता है:

return (accountNumber == DBNull.Value) ? string.Empty : accountNumber.ToString()

संपादित करें: ExecuteScalar पर ध्यान नहीं दिया गया। यदि फ़ील्ड वापसी परिणाम में अनुपस्थित है, तो यह वास्तव में शून्य देता है। इसलिए इसके बजाय उपयोग करें:

return (accountNumber == null) ? string.Empty : accountNumber.ToString() 

3
यह काम नहीं करेगा - "अकाउंटनंबर" एक डेटाबेस मूल्य नहीं है, लेकिन एक नियमित रूप से पुराना सादा पुराना .NET "ऑब्जेक्ट" उदाहरण है - आपको सामान्य "अशक्त" मूल्य के खिलाफ जांच करने की आवश्यकता है। DBNull.Value एक SqlDataReader या SqlParameter के लिए काम करेगा - लेकिन यहां इस ऑब्जेक्ट के लिए नहीं।
marc_s

आप सही हैं, मैंने कंडीशन चेक पार्ट को ऑप्टिमाइज़ करना शुरू कर दिया है, इससे पहले लाइन को नहीं देखा है। मैया पापा।
उपयोगकर्ता

आपकी पोस्ट में टाइपो है जिसे मैं वास्तव में संपादित नहीं कर सकता क्योंकि संपादित करने के लिए 6 वर्णों को बदलना आवश्यक है। क्या कोई accountNumber.TosString () को accountNumber.ToString () में बदल सकता है
Eric

@marc_s db / क्वेरी लेआउट के आधार पर, आपको उनमें से किसी एक या दोनों के खिलाफ जांच करने की आवश्यकता है। यदि WHERE किसी पंक्ति से मेल नहीं खाता है, तो आपको एक प्राप्त होगा null, यदि चयनित पंक्ति NULLमें उस कॉलम में है, तो रिटर्न वैल्यू है System.DBNull
अलेक्जेंडर

पहले मामले में @ अलेक्जेंडर में किसी भी पंक्ति का उल्लेख नहीं किया गया है- आप Convert.ToString या किसी अन्य रूपांतरित विधि पर भरोसा कर सकते हैं यदि आप उस मान के साथ ठीक हैं, जब वे null से रूपांतरण करते समय वापस आते हैं: स्ट्रिंग के लिए खाली स्ट्रिंग, संख्यात्मक मानों के लिए 0 बूलियन के लिए, डेटटाइम के लिए मिनल्यू ... msdn.microsoft.com/en-us/library/vstudio/…
Jaime

199

एक साधारण सामान्य फ़ंक्शन के साथ आप इसे बहुत आसान बना सकते हैं। बस यह करें:

return ConvertFromDBVal<string>(accountNumber);

समारोह का उपयोग:

public static T ConvertFromDBVal<T>(object obj)
{
    if (obj == null || obj == DBNull.Value)
    {
        return default(T); // returns the default value for the type
    }
    else
    {
        return (T)obj;
    }
}

1
हां, इस तरह का एक फ़ंक्शन केवल व्यावहारिक समाधान है। किसी भी तरह का इन-लाइन लॉजिक आपके द्वारा एक हजार बार कॉपी और पेस्ट करने के बाद विफल हो जाएगा। :-)
क्रिश्चियन हैटर

3
यह काम नहीं करेगा यदि आप 1 बूल में कनवर्ट करने का प्रयास करते हैं (Convert.ToBoolean (1) ठीक tho काम करता है)
रोमन एम

@roman: तो फिर हम एक अतिरिक्त चेक (नल के लिए जाँच करने से पहले) चाहते हैं कि एक बूलियन प्रकार की जाँच हो ...
IAbstract

1
यदि आप कनवर्ट फ़ंक्शंस का उपयोग करना चाहते हैं या करना चाहते हैं, तो यह काम नहीं कर रहा है। ऐसे कई परिदृश्य हैं जहाँ आप स्पष्ट कास्ट में कनवर्ट करना पसंद कर सकते हैं। @romanm ने उनमें से एक को नोट किया। एक और जब आप दशमलव के साथ काम करते हैं और विभिन्न गोपन तंत्रों के बारे में ध्यान रखते हैं जो Convert.ToInt32 और (int) उपयोग करते हैं। पूर्व दौर निकटतम सम मान तक पहुंचता है , जबकि स्पष्ट कास्ट केवल मूल्य को छोटा करता है: stackoverflow.com/questions/1608801/… यदि संभव हो तो, मैं T-SQL ISNULL फ़ंक्शन का उपयोग करके NULLs को समाप्त कर दूंगा
Jaime

2
@Jaime यह फ़ंक्शन SQL डेटा प्रकार से C # /। NET डेटा प्रकार के निहित कलाकारों की तरह कार्य करने वाला है। यदि आपको एक स्पष्ट कलाकार की आवश्यकता है, तो इस फ़ंक्शन का उपयोग न करें - इसके बजाय स्पष्ट रूप से करें।
लगाम

17

ExecuteScalar वापस आ जाएगी

  • कोई परिणाम सेट नहीं होने पर शून्य
  • अन्यथा परिणामी की पहली पंक्ति का पहला कॉलम, जो DBNull हो सकता है।

यदि आप जानते हैं कि परिणामी का पहला स्तंभ एक स्ट्रिंग है, तो सभी आधारों को कवर करने के लिए आपको अशक्त और DBNull दोनों की जांच करने की आवश्यकता है। कुछ इस तरह:

object accountNumber = ...ExecuteScalar(...);
return (accountNumber == null) ? String.Empty : accountNumber.ToString();

उपरोक्त कोड इस तथ्य पर निर्भर करता है कि DBNull.ToString एक खाली स्ट्रिंग देता है।

यदि अकाउंटनंबर दूसरे प्रकार का था (पूर्णांक कहें), तो आपको और अधिक स्पष्ट होने की आवश्यकता होगी:

object accountNumber = ...ExecuteScalar(...);
return (accountNumber == null || Convert.IsDBNull(accountNumber) ?     
         (int) accountNumber : 0;

यदि आप यह सुनिश्चित करते हैं कि आपके परिणाम में हमेशा कम से कम एक पंक्ति होगी (जैसे SELECT COUNT (*) ...), तो आप अशक्त के लिए चेक को छोड़ सकते हैं।

आपके मामले में त्रुटि संदेश "टाइप करने के लिए ऑब्जेक्ट को टाइप करने में असमर्थ 'System.DBNull' को टाइप करने के लिए 'System.String`" इंगित करता है कि आपके परिणाम सेट का पहला कॉलम DBNUll मान है। यह पहली पंक्ति में कलाकारों से स्ट्रिंग तक है:

string accountNumber = (string) ... ExecuteScalar(...);

Marc_s की टिप्पणी जिसे आपको DBNull.Value के लिए जाँचने की आवश्यकता नहीं है, गलत है।


मेरा परिणाम हमेशा एक पंक्ति नहीं लौटेगा।
सैफ खान

6

आप C # के नल कोलेसिंग ऑपरेटर का उपयोग कर सकते हैं

return accountNumber ?? string.Empty;

-1: यह संकलित नहीं करेगा: विधि एक स्ट्रिंग लौटाती है और खाता एक ऑब्जेक्ट है।
जो

2
वापसी Cmd.ExecuteScalar ()। ToString () ?? String.Empty;
चैतन्य

वापसी Cmd.ExecuteScalar ()। ToString () ने मेरे लिए काम किया
Taran

3

इस समस्या को हल करने का एक और तरीका है। अपनी स्टोर प्रक्रिया को कैसे संशोधित करें? ISNULL (अपने क्षेत्र, "") sql फ़ंक्शन का उपयोग करके, यदि आप वापसी मान शून्य है, तो आप खाली स्ट्रिंग लौटा सकते हैं।

फिर आपके पास मूल संस्करण के रूप में आपका साफ कोड है।


3

यह जेनेरिक विधि है जिसका उपयोग मैं किसी भी वस्तु को परिवर्तित करने के लिए करता हूं जो DBNull हो सकती है।

public static T ConvertDBNull<T>(object value, Func<object, T> conversionFunction)
{
    return conversionFunction(value == DBNull.Value ? null : value);
}

उपयोग:

var result = command.ExecuteScalar();

return result.ConvertDBNull(Convert.ToInt32);

कम:

return command
    .ExecuteScalar()
    .ConvertDBNull(Convert.ToInt32);

2

मुझे लगता है आप इसे इस तरह से कर सकते हैं:

string accountNumber = DBSqlHelperFactory.ExecuteScalar(...) as string;

अगर अकाउंटनंबर शून्य है तो इसका मतलब है कि यह DBNull नहीं स्ट्रिंग है :)


या return (accountNumber as string) ?? string.Empty;, अकाउंटनंबर के साथ अभी भी ए object। यदि आप अपने डेटाबेस कॉल को अपनी लाइन पर रखना पसंद करते हैं।
ब्रायन

1

String.Concat DBNull और शून्य मान को एक रिक्त स्ट्रिंग में बदल देता है।

public string GetCustomerNumber(Guid id)
{
   object accountNumber =  
          (object)DBSqlHelperFactory.ExecuteScalar(connectionStringSplendidCRM, 
                                CommandType.StoredProcedure, 
                                "spx_GetCustomerNumber", 
                                new SqlParameter("@id", id));

    return String.Concat(accountNumber);

 }

हालाँकि, मुझे लगता है कि आप कोड समझ में कुछ खो देते हैं


1
लिखने से क्या होता है return "" + accountNumber;?
ज़ेव स्पिट्ज

0

चूँकि मुझे एक ऐसा उदाहरण मिला है जो अशक्त नहीं है और अगर मेरी तुलना DBNULL से हुई है तो मुझे छूट मिली है Operator '==' cannot be applied to operands of type 'string' and 'system.dbnull', और अगर मैंने NULL की तुलना करने के लिए बदलने की कोशिश की, तो यह बस काम नहीं आया (चूंकि DBNull एक वस्तु है) यहां तक ​​कि स्वीकृत उत्तर भी।

मैंने 'कीवर्ड' का उपयोग करने का निश्चय किया है। इसलिए परिणाम बहुत पठनीय है:

data = (item is DBNull) ? String.Empty : item


-1

मैं अपने लिए इस समस्या को खत्म करने के लिए एक एक्सटेंशन का उपयोग करता हूं, जो आपके बाद हो सकता है या नहीं भी हो सकता है।

यह इस प्रकार चलता है:

public static class Extensions
{

    public String TrimString(this object item)
    {
        return String.Format("{0}", item).Trim();
    }

}

ध्यान दें:

यह एक्सटेंशन मान नहीं लौटाता nullहै! यदि आइटम nullया DBNull.Value है , तो यह एक खाली स्ट्रिंग लौटाएगा।

उपयोग:

public string GetCustomerNumber(Guid id)
{
    var obj = 
        DBSqlHelperFactory.ExecuteScalar(
            connectionStringSplendidmyApp, 
            CommandType.StoredProcedure, 
            "GetCustomerNumber", 
            new SqlParameter("@id", id)
        );
    return obj.TrimString();
}

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.