Oracle.DataAccess DataRow.Field <decimal> InvalidCastException

时间:2016-02-05 15:19:14

标签: c# oracle

在我的代码中,我使用System.Data.OracleClient进行ora数据库连接。我想用Oracle.DataAccess替换这个库(因为它已经过时了)。不幸的是,我发现DataRow.Field()抛出了InvalidCastException。与(decimal)x.Rows[0]["COLUME_NAME"]相同的行为。 System.Data.OracleClient我没有这个问题。

这是代码示例

using (var oracleConnection = new OracleConnection(connectionString))
{
    using (var command = new OracleCommand("select * from tr", oracleConnection))
    {
        var result = new DataTable();
        var adapter = new OracleDataAdapter(command);
        adapter.Fill(result);
        Console.WriteLine(result.Rows[0].Field<decimal>("TR_SEQ_NUM"));
        //Console.WriteLine((decimal)result.Rows[0]["TR_SEQ_NUM"]);
    }
}

TR_SEQ_NUM具有NUMBER(8,0)数据类型,完整异常为:

System.InvalidCastException: Specified cast is not valid.
   at System.Data.DataRowExtensions.UnboxT`1.ValueField(Object value)

使用System.Data.OracleClient但不使用Oracle.DataAccess

的代码示例

我知道我可以使用Convert.ChangeType,但我想知道是否有某种方法可以使用与System.Data.OracleClient相同的行为。重构我的所有代码会花费太多时间。

2 个答案:

答案 0 :(得分:1)

数据库中的值不是十进制数,并且盒装的int(错误消息中的&#39;值&#39;参数)不能转换为十进制,尽管将int转换为小数为OK。 This answer leads to more info

你可以看到它的实际效果:

void Main()
{
    int anInt = 5;
    object boxedInt = (object)anInt;
    decimal unboxed = Convert.ToDecimal(boxedInt); //5
    decimal unboxed2 = (decimal)boxedInt; //InvalidCastException
}

如果查看Unbox.ValueField方法,它会......

  private static T ValueField(object value)
  {
    if (DBNull.Value == value)
      throw DataSetUtil.InvalidCast(Strings.DataSetLinq_NonNullableCast((object) typeof (T).ToString()));
    return (T) value;
  }

基本上你需要

Convert.ToDecimal(rows[0]["TR_SEQ_NUM"]); 

答案 1 :(得分:0)

查看您的数据包含空值,并且您无法将可空数据转换为不可为空的十进制类型

请使用以下语句从DB

中读取可以为空的十进制列
result.Rows[0].Field<decimal?>("TR_SEQ_NUM")