将 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的主要内容,如果未能解决你的问题,请参考以下文章