I encountered an error saying that "Unable to cast object of type ‘System.Int16‘ to type ‘System.Int32‘." Isn’t it too unlogical? How come? When I try the following on immediate windows, the output as such that
reader.GetInt16(mycolumn_ordinal_value)
999
reader.GetInt32(mycolumn_ordinal_value)
Exception thrown: 'System.InvalidCastException' in Microsoft.Data.SqlClient.dll
At DB level (sqlserver), it is defined as mycolumn smallint.
When I ask it to Github Copilot it says literally,
However, when you try to use
reader.GetInt32(mycolumn), it throws a
System.InvalidCastException. This is unusual(you can’t be serious bruh!!) becauseGetInt32
should be able to handle any value thatGetInt16can handle, since
the range of a 32-bit integer (-2,147,483,648to2,147,483,647) is
much larger.
I don’t understand it. Any idea?
>Solution :
This happens because when you call SqlDataReader.GetInt32() for a short it ends up internally calling code like return (Int32)this.Value where this.Value is a boxed short – which is where the exception arises.
We can look at the source for SqlDataReader.GetInt32():
override public Int32 GetInt32(int i) {
ReadColumn(i);
return _data[i].Int32;
}
That _data is an array of type SqlBuffer. The definition of SqlBuffer.Int32 is:
internal Int32 Int32 {
get {
ThrowIfNull();
if (StorageType.Int32 == _type) {
return _value._int32;
}
return (Int32)this.Value; // anything else we haven't thought of goes through boxing.
}
}
The crucial thing here is that because the storage type doesn’t match, it returns (Int32)this.Value. In this case, this.Value is of type object, and is actually a boxed version of that actual underlying type – for your example that’s Int16.
Hence it’s trying to cast a boxed Int16 to an Int32 and it throws the exception.