将 OracleParameter.Value 转换为 Int32

Posted

技术标签:

【中文标题】将 OracleParameter.Value 转换为 Int32【英文标题】:Convert OracleParameter.Value to Int32 【发布时间】:2011-03-02 20:19:51 【问题描述】:

我有一个这样的存储过程调用:

using (OracleConnection con = new OracleConnection(ConfigurationManager.AppSettings["Database"]))
using (OracleCommand cmd = new OracleCommand("Package.Procedure", con))

   Int32 existsCount;

   cmd.CommandType = CommandType.StoredProcedure;
   cmd.Parameters.Add("successCount", OracleDbType.Int32, 0, ParameterDirection.InputOutput);
   cmd.Parameters.Add("BusinessId", OracleDbType.Int64, listRec.BusinessId, ParameterDirection.Input);

    con.Open();
    cmd.ExecuteScalar();
    con.Close();

    existsCount = Convert.ToInt32(cmd.Parameters["successCount"].Value);

    return (existsCount);

但是在这一行:

existsCount = Convert.ToInt32(cmd.Parameters["successCount"].Value);

它抛出异常“无法将 'Oracle.DataAccess.Types.OracleDecimal' 类型的对象转换为 'System.IConvertible' 类型。”

有什么想法吗?谢谢。

【问题讨论】:

【参考方案1】:

就我而言,我在 Oracle 中使用 Bulk Insert,遇到了同样的错误,让我在这里分享我的解决方案。我通过添加解决了它

oracleCommand.ArrayBindCount = datas.Count; 

那是我忘了设置ArrayBindCount 属性。

【讨论】:

【参考方案2】:

我不知道运行时的返回类型,因为执行代码在一个正在开发的跨平台数据访问框架内,所以我在参数值类型上使用了一个开关来访问底层的 Oracle[type].Value 属性用于各种 Oracle 托管数据访问类型。

public override object GetValue(IDataParameter parameter)

    if (parameter == null)
    
        throw new ArgumentNullException(nameof(parameter));
    

    // https://docs.oracle.com/cd/B19306_01/win.102/b14307/OracleDbTypeEnumerationType.htm
    if (parameter is OracleParameter)
    
        switch (parameter.Value)
        
            case OracleBinary oracleBinary:
                // returns byte[]
                return oracleBinary.Value;
            case OracleBoolean oracleBoolean:
                // returns bool
                return oracleBoolean.Value;
            case OracleDate oracleDate:
                // returns DateTime
                return oracleDate.Value;
            case OracleDecimal oracleDecimal:
                // oracleDecimal.Value is Decimal, so we convert to correct type.
                return parameter.DbType == DbType.Decimal
                    ? oracleDecimal.Value
                    : Convert.ChangeType(oracleDecimal.Value, parameter.DbType.ToType());
            case OracleIntervalDS oracleIntervalDS:
                // returns TimeSpan
                return oracleIntervalDS.Value;
            case OracleIntervalYM oracleIntervalYM:
                // returns Long
                return oracleIntervalYM.Value;
            case OracleTimeStamp oracleTimeStamp:
                // returns DateTime
                return oracleTimeStamp.Value;
            case OracleTimeStampLTZ oracleTimeStampLTZ:
                // returns DateTime
                return oracleTimeStampLTZ.Value;
            case OracleTimeStampTZ oracleTimeStampTZ:
                // returns DateTime
                return oracleTimeStampTZ.Value;
            default:
                throw new NotSupportedException(
                    parameter.Value != null
                        ? parameter.Value.GetType().Name
                        : parameter.ParameterName);
        
    
    else
    
        throw new NotSupportedException(parameter.GetType().Name);
    

【讨论】:

如果 Oracle 提供对 Value 属性的底层本机类型的隐式转换会很好。【参考方案3】:

使用起来更高效

Convert.ToInt32((decimal)(OracleDecimal)(cmd.Parameters["successCount"].Value))

【讨论】:

【参考方案4】:

我建议你转换成String,然后你再从String转换成Integer

Dim tmpIdSesiónCalificación As String = 
    parametroIdSesiónCalificación.Value.ToString
_idSesiónCalificación = Convert.ToInt32(tmpIdSesiónCalificación)

【讨论】:

【参考方案5】:

你也可以试试:

Oracle.DataAccess.Types.OracleDecimal d = (Oracle.DataAccess.Types.OracleDecimal)cmd.Parameters["successCount"].Value;

if( d.IsNull )
    existsCount = 0;
else
    existsCount = d.ToInt32( );

【讨论】:

我已经对此进行了测试,它的性能比以前的解决方案更好。 这是最正确的答案——不知道为什么一直在底部。 检查 null 是个好主意,但我忘了做。【参考方案6】:

怎么样

existsCount = int.Parse(cmd.Parameters["successCount"].Value.ToString());

【讨论】:

这并不愚蠢。如果有的话,Convert.To... 应该是更好的选择。由于 int.Parse() 基本上只是解析字符串值,这应该会增加一些开销。但是,也可能起作用的一件事(一开始没有考虑过)是:existsCount = (int)cmd.Parameters["successCount"].Value 如果 Oracle lib 提供了显式转换。 为什么选择 TryParse?如果可以解析 OracleDecimal 应该没问题。如果返回值超出 int32 范围,则抛出异常总比默默地忽略这一事实要好。在这种特殊情况下 int.Parse() 更好(只是我的意见)。 将数字类型转换为字符串只是为了将其转换回数字是错误的。 @GregZ。确实如此。 Oracle.DataAccess.Types.OracleDecimal 应该首先实现 IConvertible,所以 Convert.ToInt32(...) 会成功,但这可以完成工作。但是@Brads 解决方案Convert.ToInt32((decimal)(OracleDecimal)(cmd.Parameters["successCount"].Value)) 更好(但为时已晚:-) @MarkLauter 需要解释一下吗? Convert.ToInt32 有一个 Convert.ToInt32(object value) 重载 value: An object that implements the System.IConvertible interface 换句话说:如果类型本身正确实现 IConvertible,您不必在设计时知道类型,如果您不知道类型在设计时间。

以上是关于将 OracleParameter.Value 转换为 Int32的主要内容,如果未能解决你的问题,请参考以下文章

将字符串中大写转小写,小写转大写

Java 将图片转二进制再将二进制转成图片

PHP:数组——二维转一维,二维转三维,将特定的数据作为键名

115怎么转码

在线将文字转成语音的方法都有哪些?

将字符串转成数字