我知道这个问题的通常答案,但它们似乎并不适用。
我们有一个流程,可以遍历来自众多供应商的数据并将其纳入一个一致的流中。我们最近添加了一家供应商,要求将我们的主键更改为 bigint。
一些字符串处理在 C# 中更容易完成,所以我更改了 C# 代码
primaryKey = reader.GetInt32(0);
到
primaryKey = reader.GetInt64(0);
认为系统中较旧的供应商会直接转换为 Int64。
我让每个人都启动并运行,我注意到一些但不是所有旧供应商的记录(int32 主键)都得到了处理。查看日志文件,我在 reader.GetInt64() 调用处理一些批次时看到 InvalidCastException。
我知道通常的回答是“哦,你可能会得到空值”,但是
堆栈跟踪有
at System.Data.SqlClient.SqlBuffer.get_Int64()
但是如果没有源代码或行号,就很难走得更远。我放了
CAST(keyID as bigint) keyID
在返回批次的存储过程中,问题已经消失。不过还是很好奇。为什么在查询结果中给出 Int32 时 reader.GetInt64() 会偶尔抛出 InvalidCastException?
当查询结果中给出 Int32 时,为什么 reader.GetInt64() 会偶尔抛出 InvalidCastException?
reader.GetInt64()
应该抛出一个 InvalidCastException 异常,而不仅仅是“偶尔”,而是每一次。根据文档:
不进行任何转换;因此,检索到的数据必须已经是 64 位有符号整数。换句话说,如果列值为 Int32,那么 GetInt64 将抛出 InvalidCastException。它不会为您将 Int32 转换为 Int64。所有其他 SqlDataReader.Get... 方法也是如此。
可能最好的解决方法是调整 SQL 查询以始终返回 Int64 值,就像您所做的那样。或者,要处理 Int32 和 Int64 值,您可以将列值读取为
object
,然后使用
Convert.ToInt64(reader[0])
执行转换。