Oracle批量插入/更新报错:无法将System.DateTime[]转为System.IConvertible
解决Oracle批量插入时“Unable to cast object of type 'System.DateTime[]' to type 'System.IConvertible'”错误
错误原因
你直接将DateTime[]/string[]/decimal[]这类数组赋值给OracleParameter的Value,但默认状态下OracleCommand不支持这种数组参数传递逻辑。驱动会尝试把数组当作单个值进行类型转换,最终抛出类型不匹配的错误。
解决方案一:启用数组绑定修改现有代码
修改InsertUsingOracleBulkCopy方法,开启OracleCommand的数组绑定模式,并设置绑定数量:
public int InsertUsingOracleBulkCopy(string sInsertQuery, List<OracleParameter> spParams) { int iRet = 0; try { using (OracleCommand command = new OracleCommand()) { command.CommandType = CommandType.Text; command.Parameters.AddRange(spParams.ToArray()); command.Connection = DbConnection; command.CommandText = sInsertQuery; command.BindByName = true; // 关键:开启数组绑定,设置绑定数量为数组长度 if (spParams.Count > 0 && spParams[0].Value is Array arr) { command.ArrayBindCount = arr.Length; } iRet = command.ExecuteNonQuery(); } } catch (Exception ex) { iRet = -1; } return iRet; }
同时建议在参数初始化时补充字段长度设置,让参数定义更严谨:
// 示例:给ABC参数设置对应数据库字段的长度 opABC.Size = 12;
解决方案二:使用OracleBulkCopy(更高效的DataTable批量插入)
既然已经有现成的DataTable,直接用OracleBulkCopy是更简洁高效的方案,无需手动拆分数组:
public int InsertActualWeightTable(DataTable dt) { int iRet = dt.Rows.Count; try { dbContext.Open(); using (OracleBulkCopy bulkCopy = new OracleBulkCopy(dbContext.DbConnection)) { // 映射DataTable列与数据库表列(列名完全一致时可省略此步骤) bulkCopy.ColumnMappings.Add("CREATEDON", "CREATEDON"); bulkCopy.ColumnMappings.Add("ABC", "ABC"); bulkCopy.ColumnMappings.Add("ACTUALWEIGHT", "ACTUALWEIGHT"); bulkCopy.DestinationTableName = "ACUTALITEMSINBAG"; bulkCopy.WriteToServer(dt); } } catch (Exception e) { iRet = -1; throw e; } finally { dbContext.Close(); } return iRet; }
这种方式无需手动处理参数数组,直接通过DataTable完成批量插入,既避免了类型转换问题,性能表现也更优。
注意事项
- 使用数组绑定时,所有参数的数组长度必须保持一致;
- OracleBulkCopy需要项目引用支持该功能的Oracle驱动(如ODAC);
- 数据库
ACTUALWEIGHT字段为FLOAT类型,DataTable中对应列的decimal类型会被OracleBulkCopy自动转换,无需手动处理。
内容的提问来源于stack exchange,提问作者NoBullMan
相关产品推荐
相关产品推荐

