DataReader在Oracle中读取两位长小数相除结果时抛出'Specified cast not valid'
DataReader throws 'Specified cast not valid' when reading the result of dividing two long decimals in Oracle
我在 VB(.NET 4.0、VS2010、Oracle 10g)
中得到了以下示例
Dim objDb As New OracleOdp("my_connection_info.udl")
Dim sql = <sql>
SELECT 'okay' As PoC, TO_NUMBER('47,3222404188609999999999999999999999') / TO_NUMBER('21,3222404188609999') FROM dual
</sql>.Value
objDb.SQL = sql
Dim dr = objDb.Execute()
dr.Read()
Console.WriteLine(String.Format("Field count: {0}", dr.FieldCount))
Console.WriteLine(String.Format("First value (= 'okay'): {0}", dr(0)))
Console.WriteLine(String.Format("Second value (throws cast error): {0}", dr(1)))
OracleOdp 是自定义的 class,用于创建简单的 Oracle 连接。
执行此示例时,在尝试读取 DataReader 的第二列中的内容时,我在最后一行收到错误消息,并显示 "Specified cast is not valid" 和以下堆栈跟踪(来源:Oracle.DataAccess):
à Oracle.DataAccess.Client.OracleDataReader.GetDecimal(Int32 i)
à Oracle.DataAccess.Client.OracleDataReader.GetValue(Int32 i)
à Oracle.DataAccess.Client.OracleDataReader.get_Item(Int32 i)
à HelpPls.Module1.Main() dans C:\Users\xxxx\Documents\TempHelp\HelpPls\Module1.vb:ligne 24
à System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
à Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
à System.Threading.ThreadHelper.ThreadStart()
我被迫使用 Oracle.DataAccess DLL 版本 4.112.2.0。
每次我尝试用一个小数除以另一个小数时都会发生错误,但我不可能截断或舍入这些数字,因为它们在其他地方使用(请注意,VB 中没有!)在条件下。
如何让它发挥作用?
您通常这样做的方式是使用 OracleDecimal
数据类型。抱歉我不知道 VB.net,但本着演示这一点的精神,这里有一个简单的 C# 示例:
OracleCommand cmd = new OracleCommand(<your query>, conn);
OracleDataReader reader = cmd.ExecuteReader();
reader.Read();
OracleDecimal d1 = reader.GetOracleDecimal(1);
从这里,您可以简单地通过以下方式获得十进制值:
decimal d2 = d1.Value;
或更简洁地说,两个陈述合二为一:
decimal d = reader.GetOracleDecimal(1).Value;
综上所述,结果的精度对于小数来说太高了,这会引发错误。你真的需要双精度来完成这项工作。这些中的任何一个都应该适合你:
double d = reader.GetOracleDecimal(1).ToDouble();
或者,更好,因为你不会失去精度
double d = reader.GetDouble(1);
这几乎就是@jmcilhinney 在他的评论中所说的。
我在 VB(.NET 4.0、VS2010、Oracle 10g)
中得到了以下示例Dim objDb As New OracleOdp("my_connection_info.udl")
Dim sql = <sql>
SELECT 'okay' As PoC, TO_NUMBER('47,3222404188609999999999999999999999') / TO_NUMBER('21,3222404188609999') FROM dual
</sql>.Value
objDb.SQL = sql
Dim dr = objDb.Execute()
dr.Read()
Console.WriteLine(String.Format("Field count: {0}", dr.FieldCount))
Console.WriteLine(String.Format("First value (= 'okay'): {0}", dr(0)))
Console.WriteLine(String.Format("Second value (throws cast error): {0}", dr(1)))
OracleOdp 是自定义的 class,用于创建简单的 Oracle 连接。
执行此示例时,在尝试读取 DataReader 的第二列中的内容时,我在最后一行收到错误消息,并显示 "Specified cast is not valid" 和以下堆栈跟踪(来源:Oracle.DataAccess):
à Oracle.DataAccess.Client.OracleDataReader.GetDecimal(Int32 i)
à Oracle.DataAccess.Client.OracleDataReader.GetValue(Int32 i)
à Oracle.DataAccess.Client.OracleDataReader.get_Item(Int32 i)
à HelpPls.Module1.Main() dans C:\Users\xxxx\Documents\TempHelp\HelpPls\Module1.vb:ligne 24
à System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
à Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
à System.Threading.ThreadHelper.ThreadStart()
我被迫使用 Oracle.DataAccess DLL 版本 4.112.2.0。
每次我尝试用一个小数除以另一个小数时都会发生错误,但我不可能截断或舍入这些数字,因为它们在其他地方使用(请注意,VB 中没有!)在条件下。
如何让它发挥作用?
您通常这样做的方式是使用 OracleDecimal
数据类型。抱歉我不知道 VB.net,但本着演示这一点的精神,这里有一个简单的 C# 示例:
OracleCommand cmd = new OracleCommand(<your query>, conn);
OracleDataReader reader = cmd.ExecuteReader();
reader.Read();
OracleDecimal d1 = reader.GetOracleDecimal(1);
从这里,您可以简单地通过以下方式获得十进制值:
decimal d2 = d1.Value;
或更简洁地说,两个陈述合二为一:
decimal d = reader.GetOracleDecimal(1).Value;
综上所述,结果的精度对于小数来说太高了,这会引发错误。你真的需要双精度来完成这项工作。这些中的任何一个都应该适合你:
double d = reader.GetOracleDecimal(1).ToDouble();
或者,更好,因为你不会失去精度
double d = reader.GetDouble(1);
这几乎就是@jmcilhinney 在他的评论中所说的。