C#通过ODBC连接DB2时DataSet中DECIMAL类型数据格式错误
解决DB2 ODBC连接下DataSet中DECIMAL类型小数点丢失问题
问题原因
IBM DB2 ODBC驱动默认处理DECIMAL类型时,未正确应用缩放因子(例如DECIMAL(5,2)的数值会被放大100倍),导致DataSet中100.00变成10000,而OleDb驱动默认做了正确处理。
可行解决方案
1. 修改ODBC连接字符串参数
在连接字符串中添加DECIMALASFLOAT=0参数,强制驱动以原始DECIMAL类型返回数据,保留小数缩放:
string connStringDB2 = "Driver={IBM DB2 ODBC DRIVER};Database=你的数据库名;UID=用户名;PWD=密码;DECIMALASFLOAT=0;";
这个方法无需修改业务代码,是最推荐的方案。
2. 填充DataSet后批量修正数值
如果无法修改连接字符串,可在填充完成后,针对目标列做数值修正(除以对应小数位数的10的幂次,这里是100):
daDB2.Fill(dsDB2); // 修正指定表的指定列 foreach (DataRow dr in dsDB2.Tables[8].Rows) { if (dr["percentage"] != DBNull.Value) { dr["percentage"] = Convert.ToDecimal(dr["percentage"]) / 100; } } // 如果有多个DECIMAL列,可批量处理 foreach (DataTable dt in dsDB2.Tables) { // 可根据列名或数据类型筛选需要修正的列 var decimalColumns = dt.Columns.Cast<DataColumn>() .Where(col => col.ColumnName is "percentage" or "value"); // 自行扩展需要处理的列名 foreach (DataColumn col in decimalColumns) { foreach (DataRow dr in dt.Rows) { if (dr[col] != DBNull.Value) { // 这里假设是2位小数,根据实际DECIMAL的精度调整 dr[col] = Convert.ToDecimal(dr[col]) / 100; } } } }
3. 利用DataAdapter的FillError事件实时修正
在填充DataSet时通过事件拦截并修正数值:
OdbcDataAdapter daDB2 = new OdbcDataAdapter(cmdDB2); daDB2.FillError += (sender, e) => { // 针对目标列做修正 if (e.Column.ColumnName == "percentage") { e.Continue = true; // 忽略原错误,继续填充 e.Row[e.Column] = Convert.ToDecimal(e.Row[e.Column]) / 100; } }; daDB2.Fill(dsDB2);
4. 调整DB2存储过程返回类型(备选)
如果允许修改DB2存储过程,可将DECIMAL(5,2)类型转换为DOUBLE或显式格式化后返回,但这个方案需要修改数据库端代码,优先级较低。
内容的提问来源于stack exchange,提问作者Jenzz
相关产品推荐
相关产品推荐

