नल को SqlParameter पर असाइन करें


188

निम्नलिखित कोड एक त्रुटि देता है - "DBnull से int में कोई अंतर्निहित रूपांतरण नहीं।"

SqlParameter[] parameters = new SqlParameter[1];    
SqlParameter planIndexParameter = new SqlParameter("@AgeIndex", SqlDbType.Int);
planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex;
parameters[0] = planIndexParameter;

4
आपको मेरे विचार से AgeItem.AgeIndex को कास्ट करने की आवश्यकता है ... stackoverflow.com/questions/202271/… (btw, ==3rd लाइन के अंत में क्यों ?)
ग्रेग

जवाबों:


341

समस्या यह है कि ?:ऑपरेटर रिटर्न प्रकार निर्धारित नहीं कर सकता है क्योंकि आप या तो वापस आ रहे हैंint मान DBNull प्रकार मान, जो संगत नहीं हैं।

आप निश्चित रूप से AgeIndex के उदाहरण को टाइप करने के लिए डाल सकते हैं objectजो ?:आवश्यकता को पूरा करेगा ।

आप ??निम्न के रूप में नल- coalescing ऑपरेटर का उपयोग कर सकते हैं

SqlParameter[] parameters = new SqlParameter[1];     
SqlParameter planIndexParameter = new SqlParameter("@AgeIndex", SqlDbType.Int);
planIndexParameter.Value = (object)AgeItem.AgeIndex ?? DBNull.Value;
parameters[0] = planIndexParameter; 

यहाँ ऑपरेटर के लिए MSDN प्रलेखन से एक उद्धरण है ?:जो समस्या की व्याख्या करता है

या तो First_expression और दूसरी_expression का प्रकार समान होना चाहिए, या एक अंतर्निहित रूपांतरण एक प्रकार से दूसरे में मौजूद होना चाहिए।


जब ऑब्जेक्ट को अशक्त करने की कोशिश की जा रही है तो कोई अपवाद क्यों नहीं है? मुझे लगता है कि यह होना चाहिएAgeItem.AgeIndex as object
Niels Brinch

@ नील्स ब्रिंच, एक अपवाद नहीं होगा क्योंकि नल एक वस्तु है और जब तक आप इसे रोकने की कोशिश नहीं करते हैं, यह पूरी तरह से कानूनी है। हालाँकि, इस उदाहरण में यह आपत्तिजनक नहीं है, यह DBNull.Value है, जो वास्तव में एक वैल्यू टाइप है। ?? ऑपरेटर का कहना है कि 'अगर AgetItem.AgeIndex null है तो DBNull.Value को वापस कर दें अन्यथा AgeItem.AgeIndex' पर क्लिक करें फिर प्रतिक्रिया ऑब्जेक्ट पर डाली जाती है। अधिक जानकारी के लिए अशक्त coalescing ऑपरेटर देखें। msdn.microsoft.com/en-us/library/ms173224.aspx
क्रिस टेलर

3
तकनीकी रूप से, नल-कोलेसिंग ऑपरेटर ??का उपयोग करने वाला आपका समाधान एक ही समाधान है जैसे कि आप नियमित टर्नरी का उपयोग करने के लिए थे ?:- आपको अभी भी AgeItem.AgeIndexएक ऑब्जेक्ट पर डालने की आवश्यकता है planIndexParameter.Value = AgeItem.AgeIndex.HasValue ? (object)AgeItem.AgeIndex : DBNull.Value;:।
न्यूफर्नस्टी

यदि आप ?:एक विशेष प्रकार की तुलना करने के लिए नियमित टर्नरी का उपयोग करते थे , तो पूरी अभिव्यक्ति का काम नहीं करेगा। : आप की तरह तो गैर dbNull पैरामीटर कास्ट करने के लिए हैsomeID == 0 ? DBNull.Value : (object)someID
ingredient_15939

यह सच है, लेकिन यदि आपको फ़ंक्शन के एक प्रवेश पैरामीटर के रूप में नल-सक्षम मान का उपयोग करने की आवश्यकता है, जिसके परिणामस्वरूप SqlParameter का उपभोग होता है और यदि यह शून्य है, तो आपको त्रुटि मिली है कि यह काम नहीं कर रहा है और आपको बस सरल-उपयोग के तरीके का उपयोग करना चाहिए। उदाहरण के लिए: sample.Text.Trim ()! = ""? func (sample.Text): DBNull.Value; के रूप में काम नहीं करेगा ?: और ??
क्यूमास्टर

104

स्वीकृत उत्तर से पता चलता है कि एक कलाकार का उपयोग किया जा रहा है। हालाँकि, अधिकांश SQL प्रकारों में एक विशेष नल क्षेत्र होता है, जिसका उपयोग इस कलाकारों से बचने के लिए किया जा सकता है।

उदाहरण के लिए, SqlInt32.Null"एक DBNull का प्रतिनिधित्व करता है जिसे SqlInt32 वर्ग के इस उदाहरण को सौंपा जा सकता है।"

int? example = null;
object exampleCast = (object) example ?? DBNull.Value;
object exampleNoCast = example ?? SqlInt32.Null;

2
यह सुझाव आशाजनक लग रहा था इसलिए मैंने "System.Data.SqlTypes.SqlString.Null" की कोशिश की, लेकिन यह काम नहीं करता है। यह "नल" ('एन', 'यू', 'एल', 'एल') के वास्तविक तार को सही (शून्य) के साथ खाली छोड़ने के बजाय मैदान में डालता है। हालाँकि, पुराने 2010 "स्वीकार किए जाते हैं उत्तर" जो कास्ट (ऑब्जेक्ट) के साथ उपयोग करता है ?? DBNull.Value सही तरीके से काम करता है। (मैंने जो ADO.NET प्रदाता का उपयोग किया था वह SQLite था लेकिन मुझे यकीन नहीं है कि अगर इससे कोई फ़र्क पड़ता है।) मेरा सुझाव है कि अन्य लोग ब्रायन की टिप का ध्यानपूर्वक परीक्षण करते हैं ताकि यह सुनिश्चित हो सके कि अशक्त व्यवहार अपेक्षित है।
जसदेव

6
@ जेस्देव: मैं एक उच्च प्रतिनिधि उपयोगकर्ता (मुझे लगता है कि मार्क ग्रेवेल) के लिए एक टिप्पणी में इस चाल का वर्णन करते हुए अस्पष्ट रूप से याद करता हूं और कहा जा रहा है कि यह केवल Microsoft SQL सर्वर पर काम करता है।
ब्रायन

@JasDev प्रदाता वह अंतर होगा जो ब्रेन पॉइंट आउट के रूप में SQL सर्वर में काम करता है।
लंकिमार्ट

यह उत्तर केवल एक स्पष्ट कास्ट को एक implicit.one के साथ ऑब्जेक्ट में बदल देता है। नमूना कोड में, exampleNoCastऑब्जेक्ट घोषित किया जाता है, इसलिए ऑब्जेक्ट के लिए कास्ट अभी भी होता है। अगर, ओपी के कोड की तरह, मूल्य SqlParameter.Value को सीधे असाइन किया गया है, जो कि टाइप ऑब्जेक्ट का भी है, तो आप अभी भी कास्ट प्राप्त करते हैं।
स्कॉट

31

आपको DBNull.ValueSQLCommand के भीतर एक अशक्त पैरामीटर के रूप में पास करने की आवश्यकता है , जब तक कि संग्रहीत प्रक्रिया के भीतर एक डिफ़ॉल्ट मान निर्दिष्ट नहीं किया जाता है (यदि आप संग्रहीत प्रक्रिया का उपयोग कर रहे हैं)। DBNull.Valueक्वेरी निष्पादन से पहले किसी भी लापता पैरामीटर के लिए असाइन करने के लिए सबसे अच्छा तरीका है , और उसके बाद निम्नलिखित कार्य करना होगा।

foreach (SqlParameter parameter in sqlCmd.Parameters)
{
    if (parameter.Value == null)
    {
        parameter.Value = DBNull.Value;
    }
}

अन्यथा इस लाइन को बदलें:

planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex;

निम्नलिखित नुसार:

if (AgeItem.AgeIndex== null)
    planIndexParameter.Value = DBNull.Value;
else
    planIndexParameter.Value = AgeItem.AgeIndex;

क्योंकि आप सशर्त विवरण में विभिन्न प्रकार के मूल्यों का उपयोग नहीं कर सकते हैं, क्योंकि DBNull और int एक दूसरे से अलग हैं। आशा है कि यह मदद करेगा।


यह उत्तर वास्तव में अच्छा है क्योंकि यह हर तरह से संभव है। मुझे पहला दृष्टिकोण पसंद है, मैं आमतौर पर ईएफ का उपयोग करता हूं लेकिन इस आवश्यकता में ऐसा नहीं कर सका और यह मुझे बहुत समय बचाता है। धन्यवाद!
Leandro

23

कोड की एक पंक्ति के साथ, यह प्रयास करें:

var piParameter = new SqlParameter("@AgeIndex", AgeItem.AgeIndex ?? (object)DBNull.Value);

5

इसे इस्तेमाल करे:

SqlParameter[] parameters = new SqlParameter[1];    
SqlParameter planIndexParameter = new SqlParameter("@AgeIndex", SqlDbType.Int);

planIndexParameter.IsNullable = true; // Add this line

planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex== ;
parameters[0] = planIndexParameter;

5

यदि आप सशर्त (टर्नरी) ऑपरेटर का उपयोग करते हैं, तो संकलक को दोनों प्रकारों के बीच एक अंतर्निहित रूपांतरण की आवश्यकता होती है, अन्यथा आपको अपवाद मिलता है।

तो आप इसे दोनों में से किसी एक को चुनकर ठीक कर सकते हैं System.Object:

planIndexParameter.Value = (AgeItem.AgeIndex== null) ? DBNull.Value : (object) AgeItem.AgeIndex;

लेकिन जब से परिणाम वास्तव में सुंदर नहीं है और आपको हमेशा इस कास्टिंग को याद रखना है, आप इसके बजाय इस तरह के एक विस्तार विधि का उपयोग कर सकते हैं:

public static object GetDBNullOrValue<T>(this T val)
{
    bool isDbNull = true;
    Type t = typeof(T);

    if (Nullable.GetUnderlyingType(t) != null)
        isDbNull = EqualityComparer<T>.Default.Equals(default(T), val);
    else if (t.IsValueType)
        isDbNull = false;
    else
        isDbNull = val == null;

    return isDbNull ? DBNull.Value : (object) val;
}

तब आप इस संक्षिप्त कोड का उपयोग कर सकते हैं:

planIndexParameter.Value = AgeItem.AgeIndex.GetDBNullOrValue();

1

मेरी राय में SqlCommand वर्ग के पैरामीटर गुण के साथ ऐसा करने का बेहतर तरीका है :

public static void AddCommandParameter(SqlCommand myCommand)
{
    myCommand.Parameters.AddWithValue(
        "@AgeIndex",
        (AgeItem.AgeIndex== null) ? DBNull.Value : AgeItem.AgeIndex);
}

लेकिन अगर मूल्य है DBNull.Value, तो ADO.NET के पास कुछ कठिन समय हो सकता है जो यह अनुमान लगा सकता है कि SqlDbType क्या हो सकता है ........ यह सुविधाजनक है - लेकिन थोड़ा खतरनाक है ....
marc_s

1

उपलब्ध अशक्त (टी) संरचना का उपयोग करने पर विचार करें। यदि आपके पास है, तो यह आपको केवल मान सेट करने देता है, और आपकी SQL कमांड ऑब्जेक्ट आपके मान को बिना किसी परेशानी के अनुसार अशक्त मान और प्रक्रिया को पहचानेंगी।


1
if (_id_categoria_padre > 0)
{
    objComando.Parameters.Add("id_categoria_padre", SqlDbType.Int).Value = _id_categoria_padre;
}
else
{
    objComando.Parameters.Add("id_categoria_padre", DBNull.Value).Value = DBNull.Value;
}

0

इसे इस्तेमाल करे:

if (AgeItem.AgeIndex != null)
{
   SqlParameter[] parameters = new SqlParameter[1];
   SqlParameter planIndexParameter = new SqlParameter("@AgeIndex", SqlDbType.Int);
   planIndexParameter.Value = AgeItem.AgeIndex;
   parameters[0] = planIndexParameter;
}

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


लेकिन अब, आप सिर्फ एक पैरामीटर को छोड़ रहे हैं - मुझे अत्यधिक संदेह है कि संग्रहीत प्रक्रिया इस बारे में खुश होगी .... सबसे अधिक संभावना है, कॉल "पैरामीटर @AgeIndex के लिए कोई मूल्य नहीं बताएगा जो कि अपेक्षित था"। ।
marc_s

वाह। कठोर। यदि पैरामीटर पारित नहीं किया जाता है, तो बस एक डिफ़ॉल्ट मान के लिए संग्रहीत खरीद लिखें। (@AgeIndex int = 0)। हमेशा होता है। क्लाइंट या तो डिफ़ॉल्ट को स्वीकार कर सकता है, या पैरामीटर को पारित करके इसे ओवरराइड कर सकता है। क्यों होता है पतन?
Flipster

0

कुछ इस तरह की कोशिश करो:

if (_id_categoria_padre > 0)
{
    objComando.Parameters.Add("id_categoria_padre", SqlDbType.Int).Value = _id_categoria_padre;
}
else
{
    objComando.Parameters.Add("id_categoria_padre", DBNull.Value).Value = DBNull.Value;
}

0
int? nullableValue = null;
object nullableValueDB
{
   get{
       if(nullableValue==null)
          return DBNull.Value;
       else
          return (int)nullableValue;
   }
}

मैं ऐसे ही हल कर रहा हूं।


0
if (AgeItem.AgeIndex== null)  
    cmd.Parameters.Add(new SqlParameter("ParaMeterName", SqlDbType.DateTime).Value = DBNull);  
else  
    cmd.Parameters.Add(new SqlParameter("ParaMeterName", SqlDbType.DateTime).Value = AgeItem.AgeIndex);

0

यह वही है जो मैं बस करता हूँ ...

        var PhoneParam = new SqlParameter("@Phone", DBNull.Value);
        if (user.User_Info_Phone != null)
        {
            PhoneParam.SqlValue = user.User_Info_Phone;
        }

        return this.Database.SqlQuery<CustLogonDM>("UpdateUserInfo @UserName, @NameLast, @NameMiddle, @NameFirst, @Address, @City, @State, @PostalCode, @Phone",
            UserNameParam, NameLastParam, NameMiddleParam, NameFirstParam, AddressParam, CityParam, StateParam, PostalParam, PhoneParam).Single();

0
            dynamic psd = DBNull.Value;

            if (schedule.pushScheduleDate > DateTime.MinValue)
            {
                psd = schedule.pushScheduleDate;
            }


            sql.DBController.RunGeneralStoredProcedureNonQuery("SchedulePush",
                     new string[] { "@PushScheduleDate"},
                     new object[] { psd }, 10, "PushCenter");

0

इसके लिए एक सरल विस्तार विधि होगी:

    public static void AddParameter(this SqlCommand sqlCommand, string parameterName, 
        SqlDbType sqlDbType, object item)
    {
        sqlCommand.Parameters.Add(parameterName, sqlDbType).Value = item ?? DBNull.Value;
    }

0

मैं एक सरल विधि का उपयोग करता हूं जिसमें एक अशक्त जांच होती है।

    public SqlParameter GetNullableParameter(string parameterName, object value)
    {
        if (value != null)
        {
            return new SqlParameter(parameterName, value);
        }
        else
        {
            return new SqlParameter(parameterName, DBNull.Value);
        }
    }

1
क्या वह सशर्त तर्क पीछे है? क्या DBNull.Value पहले वाले में होना चाहिए?
मार्क शुल्त्स

निश्चित रूप से है। फिक्स्ड। धन्यवाद।
ज़ी एक

0

मेरा कोड, वास्तविक परियोजना में काम कर रहा है, टेरीनेरी संचालक को देखो, क्योंकि यह मेरे लिए सबसे अच्छा तरीका है

    public bool Key_AddExisting
    (
          string clave
        , int? idHito_FileServer
        , int? idTipoDocumental_Almacen
        , string tipoExp_CHJ
        , int idTipoExp_Verti2
        , int idMov_Verti2
    )
    {
        List<SqlParameter> pars = new List<SqlParameter>()
        {
              new SqlParameter { ParameterName = "@Clave", Value = clave }
    LOOK -> , idHito_FileServer == null ? new SqlParameter { ParameterName = "@IdHito_FileServer", Value = DBNull.Value } : new SqlParameter { ParameterName = "@IdHito_FileServer", Value = idHito_FileServer }
    LOOK -> , idTipoDocumental_Almacen == null ? new SqlParameter { ParameterName = "@IdTipoDocumental_Almacen", Value = DBNull.Value } : new SqlParameter { ParameterName = "@IdTipoDocumental_Almacen", Value = idTipoDocumental_Almacen }
            , new SqlParameter { ParameterName = "@TipoExp_CHJ", Value = tipoExp_CHJ }
            , new SqlParameter { ParameterName = "@IdTipoExp_Verti2", Value = idTipoExp_Verti2 }
            , new SqlParameter { ParameterName = "@IdMov_Verti2", Value = idMov_Verti2 }
        };

        string sql = "INSERT INTO [dbo].[Enlaces_ClavesCHJ_MovimientosVerti2] " +
            "( " +
            "  [Clave] " +
            ", [IdHito_FileServer] " +
            ", [IdTipoDocumental_Almacen] " +
            ", [TipoExp_CHJ] " +
            ", [IdTipoExp_Verti2] " +
            ", [IdMov_Verti2] " +
            ") " +
            "VALUES" +
            "( " +
            "  @Clave" +
            ", @IdHito_FileServer" +
            ", @IdTipoDocumental_Almacen" +
            ", @TipoExp_CHJ" +
            ", @IdTipoExp_Verti2" +
            ", @IdMov_Verti2" +
            ")";

        return DbBasic.ExecNonQuery(ref this.conn, sql, pars);
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.