प्रश्न:सी # में [TYPE] से nullable <[TYPE]> कैसे परिवर्तित करें?
मैंने एक SQL परिणाम को डेटाटेबल के बजाय कक्षा की सूची के रूप में पुनर्प्राप्त करने के लिए एक विधि लिखा है। समस्या यह है कि, मेरे पास डेटाबेस में एक int फ़ील्ड है, जो शून्य है।
अगर मैं एक NULL
int
, DataReader
रिटर्न अशक्त के बजाय DbNull.Value
के साथ एक पंक्ति मारा। तो System.Convert.ChangeType(objVal, fi.FieldType)
एक अपवाद फेंकता है, क्योंकि यह DbNull
को int
में परिवर्तित नहीं कर सकता है।
अब तक इतना बुरा है। मैंने सोचा कि मैं समस्या हल हो गया था, जब मैं सिर्फ objVal
DbNull.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>
बनाने के लिए।
क्या आपने एंटिटी फ्रेमवर्क देखा है? Http: //msdn.microsoft.com/en-us/library/aa697427 (v = vs.80) .aspx – Bas
@ बास: हाँ, और यह बहुत धीमा है। –
लेकिन प्रतिबिंब से बहुत तेज़, और यदि आप AsNoTracking का उपयोग करते हैं तो यह लगभग datareader – Bas