【问题标题】:Oracle.DataAccess DataRow.Field<decimal> InvalidCastExceptionOracle.DataAccess DataRow.Field<decimal> InvalidCastException
【发布时间】:2016-05-15 15:09:39
【问题描述】:

在我的代码中,我使用System.Data.OracleClient 进行数据库连接。我想用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 相同的行为。重构我的所有代码会花费太多时间。

【问题讨论】:

  • 使用 Oracle.ManagedDataAccess.Client; //使用托管版本调用 tbl.Rows[0][0].GetType(); 时会发生什么? .Field 在您使用列索引/名称的新版本中是不可能的。你将不得不重构,System.Data.OracleClient 已经过时了,但是当你填表时应该为你处理转换......
  • 另外,Number(8,0) 不会是小数,你为什么要把它转换成一个?很少需要使用 Decimal,并不是说它会导致您遇到的问题,而是在应用程序运行时可能会为您节省一些内存
  • 我同意 LessNoviceProgrammer。我认为NUMBER(8,0) 的正确类型是int...

标签: c# oracle


【解决方案1】:

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

请使用以下语句从 DB 中读取可为空的十进制列

result.Rows[0].Field<decimal?>("TR_SEQ_NUM")

【讨论】:

    【解决方案2】:

    数据库中的值不是小数,并且装箱的 int(错误消息中的 'value' 参数)不能转换为小数,尽管将 int 转换为小数是可以的。 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"]); 
    

    【讨论】:

      猜你喜欢
      • 2017-06-28
      • 1970-01-01
      • 2018-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多