You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Npgsql时字符串转数值/DateTime类型失败的问题排查

Npgsql类型转换错误排查:System.InvalidCastException字符串转Numeric失败

错误现象

执行代码时反复触发以下异常:

System.InvalidCastException: 'Can't write CLR type System.String with handler type NumericHandler'

错误本质明确:向PostgreSQL的Numeric类型字段传入了CLR的String类型值,二者类型不匹配。

场景背景

正在将旧VB代码迁移至C#,VB中用于存储数值的变量初始声明为字符串,且包含字符串操作逻辑。计划先完成字符串处理,再通过Convert.ToDecimal()转换为数值类型后传入Npgsql参数,但执行报错。

代码问题分析

初始变量声明

string tno = "";
string iw = "";
string ws = "";
string ftg = "0";
string hl = "0";
string ll = "0";
string date = "2012/02/04";
string va = "0";
string dev = "0";

尝试的转换操作

Convert.ToDecimal(tno);

SQL语句

string sqlString = @"UPDATE header
SET ft = @gftg, high_limit=@ghl, low_limit=@gll, start_date = @gsdd, avg_ga = @gvgga, std_dev = @gstd
WHERE cmpy_id = 'ABC' and tag_no = @gto and ip_num = @gim";

Npgsql参数绑定(错误代码)

cmd.Parameters.Add("@gim", NpgsqlTypes.NpgsqlDbType.Varchar).Value = iw;                              
cmd.Parameters.Add("@gftg", NpgsqlTypes.NpgsqlDbType.Numeric).Value = ftg;                            
cmd.Parameters.Add("@ghl", NpgsqlTypes.NpgsqlDbType.Numeric).Value = hl;                              
cmd.Parameters.Add("@gll", NpgsqlTypes.NpgsqlDbType.Numeric).Value = ll;                              
cmd.Parameters.Add("@gsdd", NpgsqlTypes.NpgsqlDbType.Date).Value = date;                             
cmd.Parameters.Add("@gvgga", NpgsqlTypes.NpgsqlDbType.Numeric).Value = va;                              
cmd.Parameters.Add("@gstd", NpgsqlTypes.NpgsqlDbType.Numeric).Value = dev;

核心问题

  1. 转换操作未生效:Convert.ToDecimal(tno)仅执行了转换计算,但未将结果赋值给变量。原变量ftg、hl等仍为字符串类型,绑定参数时传入的还是字符串,导致类型不匹配。
  2. 错误的变量声明尝试:直接用字符串字面量初始化decimal变量会触发编译错误,C#不支持这种隐式转换:
// 编译错误:无法将字符串转换为decimal
decimal ftg = "0";

解决方案

正确的转换与参数绑定

转换时必须将结果赋值给变量,再将转换后的数值类型变量绑定到参数:

// 先完成字符串处理逻辑...

// 转换为decimal类型并赋值
decimal ftgDecimal = Convert.ToDecimal(ftg);
decimal hlDecimal = Convert.ToDecimal(hl);
decimal llDecimal = Convert.ToDecimal(ll);
decimal vaDecimal = Convert.ToDecimal(va);
decimal devDecimal = Convert.ToDecimal(dev);
// 日期需转换为DateTime类型,不能直接传字符串
DateTime dateValue = DateTime.Parse(date);

// 绑定参数时传入转换后的数值/日期类型
cmd.Parameters.Add("@gim", NpgsqlTypes.NpgsqlDbType.Varchar).Value = iw;                              
cmd.Parameters.Add("@gftg", NpgsqlTypes.NpgsqlDbType.Numeric).Value = ftgDecimal;                            
cmd.Parameters.Add("@ghl", NpgsqlTypes.NpgsqlDbType.Numeric).Value = hlDecimal;                              
cmd.Parameters.Add("@gll", NpgsqlTypes.NpgsqlDbType.Numeric).Value = llDecimal;                              
cmd.Parameters.Add("@gsdd", NpgsqlTypes.NpgsqlDbType.Date).Value = dateValue;                             
cmd.Parameters.Add("@gvgga", NpgsqlTypes.NpgsqlDbType.Numeric).Value = vaDecimal;                              
cmd.Parameters.Add("@gstd", NpgsqlTypes.NpgsqlDbType.Numeric).Value = devDecimal;

可选优化:提前使用正确类型

如果字符串操作逻辑可调整,建议直接将变量声明为对应类型,减少转换步骤:

string tno = "";
string iw = "";
string ws = "";
decimal ftg = 0;
decimal hl = 0;
decimal ll = 0;
DateTime date = new DateTime(2012, 2, 4);
decimal va = 0;
decimal dev = 0;

// 若需字符串操作,可临时转换为字符串处理后再转回decimal
// 例如:
ftg = decimal.Parse(ftg.ToString().Replace(",", "."));

关键说明

  • PostgreSQL的Numeric类型优先对应CLR的decimal类型(可保证精度,适合数值计算场景),double也可兼容,但存在精度丢失风险。
  • 日期类型不能直接传字符串,必须转换为DateTime类型后传入,否则会触发类似的类型转换错误。

内容的提问来源于stack exchange,提问作者austin-smith-999

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 23:00:54