我有一个包含2列的表(string& int)。 int列的当前值为-1
。
使用SQLDataReader
我正在读取此表中的行:
public class MyObject
{
public string Name;
public long Number;
}
using (SqlDataReader dataReader = command.ExecuteReader())
{
MyObject o = new MyObject()
while (dataReader.Read())
{
o.Name= dataReader.GetString(0);
o.Number = dataReader.GetInt64(1);
}
}
但是,在阅读InvalidCastException
列时,我收到了Number
。我在这里缺少什么?
答案 0 :(得分:5)
SqlDataReader.GetInt64的评论部分指出:
不进行转换;因此,检索的数据必须已经是64位有符号整数。
顺便说一下:如果您的值可以为空,请不要忘记调用IsDBNUll
您确定数据库中检索到的数据是 bigint 吗?如果是int或nchar / nvarchar,则应使用相应的函数并将其转换或解析为System.Int64
有人建议改善代码的健壮性
答案 1 :(得分:1)
您需要通过int
将其作为GetInt32
阅读。您不需要将其强制转换为long
,因为运行时可以隐式地执行此操作。
运行时不会让你从object
解除绑定到另一种数据类型,而无需先将object
解除绑定到object
的正确内部数据类型是,然后铸造到下一个。这个怪癖与数据阅读器无关:
static void Main(string[] args)
{
int i = 1;
object o = i;
long l = (long)o; // invalid cast, trying to unbox to something other than the original type
l = (long)(int)o; // No invalid cast, un-boxed to int then cast to long.
}
特别是使用SqlDataReader
,因为您的基础类型不是Int64
,它会在内部尝试直接解除错误类型:
internal Int64 Int64 {
get {
ThrowIfNull();
if (StorageType.Int64 == _type) {
return _value._int64;
}
return (Int64)this.Value; // anything else we haven't thought of goes through boxing.
}
// set excluded for brevity
}
TL; DR;做文件所说的(正如HaraldDutch的回答所建议的那样),并阅读正确的预期类型。
答案 2 :(得分:0)
确保您尝试获取的值在数据库中是bigint。 BIGINT相当于Int64(在C#中很长)。如果它不是bigint,请尝试使用Convert.ToInt64()
答案 3 :(得分:0)
好的,可以得出正确的结论。你的列DataType是int而不是bigint所以你不能通过.GetInt64()调用它,因为它是未装箱的
您无法取消选择Int32 - > Int64的
正如@Adam Houldsworth所说 -
"阅读给出的内容,而不是您想要的内容"
要解决您的问题,只需将GetInt64()切换为GetInt32()即可。见下文:
using (SqlDataReader dataReader = command.ExecuteReader())
{
MyObject o = new MyObject()
while (dataReader.Read())
{
o.Name= dataReader.GetString(0);
o.Number = dataReader.GetInt32(1); // safe implicitly cast no need to make it manually
}
}
如果您不了解确切的基础数据类型您可以随时以其他方式执行此操作。请参阅以下代码:
using (SqlDataReader dataReader = command.ExecuteReader())
{
MyObject o = new MyObject()
while (dataReader.Read())
{
o.Name = dataReader.GetString(0);
var number = dataReader.GetValue(1);
try
{
o.Number = Convert.ToInt64(number);
}
catch(InvalidCastException)
{
Throw new Exception("Underlying DataType is not convertable to int 64.");
}
}
}
答案 4 :(得分:0)
如果要将SQLDataReader对象从(object {int})开箱到很长一段时间,应该知道,没有直接的方法。例如此代码
long _result = (long)(sqlDR["IntTypeField"] ?? 0L);
将生成“ System.InvalidCastException”。 您应该使用更全面的功能,像这样
public static T NvlO<T>(object a, T b)
{
if (a == null)
return b;
else
{
var lSrcType = a.GetType();
var lDestType = typeof(T);
if (lDestType.IsValueType && lDestType.IsAssignableFrom(lSrcType))
return (T)a;
var lDestTC = TypeDescriptor.GetConverter(typeof(T));
if (lDestTC.CanConvertFrom(lSrcType))
return (T)lDestTC.ConvertFrom(a);
else
{
var lSrcTC = TypeDescriptor.GetConverter(lSrcType);
String lTmp = lSrcTC.ConvertToInvariantString(a);
return (T)lDestTC.ConvertFromInvariantString(lTmp);
}
}
}