2012-06-14 8 views
5

प्रश्न:सी # में [TYPE] से nullable <[TYPE]> कैसे परिवर्तित करें?

मैंने एक SQL परिणाम को डेटाटेबल के बजाय कक्षा की सूची के रूप में पुनर्प्राप्त करने के लिए एक विधि लिखा है। समस्या यह है कि, मेरे पास डेटाबेस में एक int फ़ील्ड है, जो शून्य है।

अगर मैं एक NULLint, DataReader रिटर्न अशक्त के बजाय DbNull.Value के साथ एक पंक्ति मारा। तो System.Convert.ChangeType(objVal, fi.FieldType) एक अपवाद फेंकता है, क्योंकि यह DbNull को int में परिवर्तित नहीं कर सकता है।

अब तक इतना बुरा है। मैंने सोचा कि मैं समस्या हल हो गया था, जब मैं सिर्फ objValDbNull.Value करने के लिए और अगर सही है की तुलना में, बजाय ऐसा किया: System.Convert.ChangeType(null, fi.FieldType)

दुर्भाग्य से, मैं सिर्फ एहसास हुआ, जिसके परिणामस्वरूप पूर्णांक प्रकार शून्य के बजाय 0 है।

तो मैं सिर्फ Nullable<int> को मेरी कक्षा में पूर्णांक प्रकार बदलने की कोशिश की, लेकिन अब मैं समस्या यह है कि जब एक मूल्य DbNull.Value नहीं है, ChangeType एक अपवाद फेंकता है, क्योंकि यह nullable<int> को int परिवर्तित नहीं कर सकते हैं ...

तो अब मैं datareader द्वारा लौटाई गई वस्तु के प्रकार का पता लगाने की कोशिश करता हूं, और इसे एक शून्य मूल्य में परिवर्तित करता हूं।

tTypeForNullable सही ढंग से Nullable<int> के रूप में दिखाया गया है। लेकिन जब मैं परिणाम प्रकार को देखता हूं, तो मुझे मिलता है: int

वह क्यों है? और अधिक महत्वपूर्ण: मैं इसे ठीक से कैसे कर सकता हूं?

कृपया ध्यान दें कि क्योंकि एक वस्तु एक वस्तु है, इसलिए मैं Nullable<int> बनाने के लिए एक सामान्य विधि का उपयोग नहीं कर सकता।

public virtual System.Collections.Generic.IList<T> GetList<T>(System.Data.IDbCommand cmd) 
     { 
      System.Collections.Generic.List<T> lsReturnValue = new System.Collections.Generic.List<T>(); 
      T tThisValue = default(T); 
      Type t = typeof(T); 

      lock (cmd) 
      { 
       using (System.Data.IDataReader idr = ExecuteReader(cmd)) 
       { 

        lock (idr) 
        { 

         while (idr.Read()) 
         { 
          //idr.GetOrdinal("") 
          tThisValue = Activator.CreateInstance<T>(); 

          // Console.WriteLine(idr.FieldCount); 
          for (int i = 0; i < idr.FieldCount; ++i) 
          { 
           string strName = idr.GetName(i); 
           object objVal = idr.GetValue(i); 


           System.Reflection.FieldInfo fi = t.GetField(strName); 
           //Type tttttt = fi.FieldType; 
           if (fi != null) 
           { 
            //fi.SetValue(tThisValue, System.Convert.ChangeType(objVal, fi.FieldType)); 
            if (objVal == System.DBNull.Value) 
            { 
             objVal = null; 
             fi.SetValue(tThisValue, null); 
            } 
            else 
            { 
             //System.ComponentModel.TypeConverter conv = System.ComponentModel.TypeDescriptor.GetConverter(fi.FieldType); 

             bool bisnull = IsNullable(objVal); 
             bool bisnullt = IsNullable(fi.FieldType); 

             if (bisnullt) 
             { 
              Type tTypeForNullable = typeof(Nullable<>).MakeGenericType(objVal.GetType()); 

              //object result = Activator.CreateInstance(tTypeForNullable, new object[] { objVal }); 
              //object result = Activator.CreateInstance(typeof(Nullable<int>), new object[] { objVal }); 
              object result = Activator.CreateInstance(tTypeForNullable, objVal); 
              Type tres = result.GetType(); 
              fi.SetValue(tThisValue, System.Convert.ChangeType(result, fi.FieldType)); 
             } 
             fi.SetValue(tThisValue, System.Convert.ChangeType(objVal, fi.FieldType)); 
            } 
           } 
           else 
           { 
            System.Reflection.PropertyInfo pi = t.GetProperty(strName); 
            if (pi != null) 
            { 
             //pi.SetValue(tThisValue, System.Convert.ChangeType(objVal, pi.PropertyType), null); 


             if (objVal == System.DBNull.Value) 
             { 
              objVal = null; 
              pi.SetValue(tThisValue, null, null); 
             } 
             else 
             { 
              pi.SetValue(tThisValue, System.Convert.ChangeType(objVal, pi.PropertyType), null); 
             } 


            } 
            // Else silently ignore value 
           } // End else of if (fi != null) 

           //Console.WriteLine(strName); 
          } // Next i 

          lsReturnValue.Add(tThisValue); 
         } // Whend 

         idr.Close(); 
        } // End Lock idr 

       } // End Using idr 

      } // End lock cmd 

      return lsReturnValue; 
     } // End Function GetList 
इस के साथ

:

bool bisnull = IsNullable(objVal); 
bool bisnullt = IsNullable(fi.FieldType); 

if (bisnullt) 
{ 
    Type tTypeForNullable = typeof(Nullable<>).MakeGenericType(objVal.GetType()); 

    //object result = Activator.CreateInstance(tTypeForNullable, new object[] { objVal }); 
    //object result = Activator.CreateInstance(typeof(Nullable<int>), new object[] { objVal }); 
    object result = Activator.CreateInstance(tTypeForNullable, objVal); 
    Type tres = result.GetType(); 
    fi.SetValue(tThisValue, System.Convert.ChangeType(result, fi.FieldType)); 
} 

यहाँ संदर्भ के लिए पूरा दिनचर्या है

public System.Data.IDataReader ExecuteReader(System.Data.IDbCommand cmd) 
     { 
      System.Data.IDataReader idr = null; 

      lock(cmd) 
      { 
       System.Data.IDbConnection idbc = GetConnection(); 
       cmd.Connection = idbc; 

       if (cmd.Connection.State != System.Data.ConnectionState.Open) 
        cmd.Connection.Open(); 

       idr = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection); 
      } // End Lock cmd 

      return idr; 
     } // End Function ExecuteReader 

कृपया ध्यान दें कि क्योंकि प्रकार एक वस्तु है, मैं एक सामान्य विधि का उपयोग नहीं कर सकते Nullable<int> बनाने के लिए।

+1

क्या आपने एंटिटी फ्रेमवर्क देखा है? Http: //msdn.microsoft.com/en-us/library/aa697427 (v = vs.80) .aspx – Bas

+0

@ बास: हाँ, और यह बहुत धीमा है। –

+0

लेकिन प्रतिबिंब से बहुत तेज़, और यदि आप AsNoTracking का उपयोग करते हैं तो यह लगभग datareader – Bas

उत्तर

3

आप मुक्केबाजी रहे हैं - और एक नल मान प्रकार के लिए एक बॉक्सिंग आपरेशन के परिणाम कभी नहीं उस प्रकार के एक बॉक्स्ड मूल्य है। यह या तो शून्य या एक गैर-शून्य मूल्य प्रकार है। अधिक जानकारी के लिए MSDN देखें।

+1

ग्रेट - अब मुझे समस्या पता है लेकिन समाधान नहीं ... –

+0

@Quandary: यह वास्तव में स्पष्ट नहीं है कि आप ईमानदार होने के लिए क्या करने की कोशिश कर रहे हैं। क्या समस्या "प्रतिबिंब द्वारा एक शून्य क्षेत्र को स्थापित करना" है? डेटाबेस पहलुओं आदि से इसे अलग करने के लायक होंगे –

+0

असली समस्या यह है कि System.Convert.ChangeType शून्य प्रकारों के लिए काम नहीं करता है। लेकिन मैंने अभी देखा कि मेरे int के लिए मूल का क्षेत्र वास्तव में एक वर्चर था ... यही कारण है कि कन्वर्ट आवश्यक था। अब शून्य के साथ, सबकुछ ठीक काम करता है, अगर मैं फाई टाइप करता हूं तो मैं कन्वर्ट नहीं कर सकता। फील्डटाइप शून्य है। –

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