Npgsql调用PostgreSQL存储过程遇类型转换错误求助
解决Npgsql调用PostgreSQL存储过程时的"Can't write CLR type System.String with handler type DateHandler"错误
核心问题分析
错误根源是将字符串类型值传递给了PostgreSQL的Date类型参数——即便指定了NpgsqlDbType.Date,Npgsql仍要求接收.NET DateTime类型对象,而非字符串格式的日期。此外代码还存在参数名不匹配、数据读取索引错误的问题。
分步修正方案
1. 修正参数传递类型与参数名
将字符串日期转换为DateTime对象,同时确保参数名与存储过程定义的orderdate完全一致:
// 替换原有参数添加代码 pgcom.Parameters.AddWithValue("orderdate", NpgsqlTypes.NpgsqlDbType.Date, DateTime.Parse("2022-01-01")); // 建议用DateTime.TryParse做格式校验,避免无效日期报错
2. 修正数据读取索引
存储过程返回两个字段:count(albumid)(索引0)和extract(month FROM orderdate)(索引1),原代码错误使用了索引1和2,修正如下:
while (pgreader.Read()) { int albumCount = pgreader.GetInt32(0); int month = pgreader.GetInt32(1); }
3. 可选优化:明确存储过程返回类型(消除SETOF record歧义)
当前存储过程返回SETOF record,调用时需明确返回结构,建议修改为返回具体复合类型,提升可读性与稳定性:
CREATE OR REPLACE FUNCTION public.getmonthfromdatetestO( orderdate date) RETURNS TABLE(album_count integer, yr_month integer) LANGUAGE 'sql' COST 100 VOLATILE PARALLEL UNSAFE ROWS 1000 AS $BODY$ SELECT count(albumid)::integer, extract(month FROM orderdate)::integer AS yr_month FROM public.orderalbum WHERE extract(year FROM orderdate) = 2022 GROUP BY albumid, orderdate $BODY$;
完整修正后的C#代码示例
[HttpGet] public ActionResult getmonthSales() { string sql3 = @"getmonthfromdatetestO"; conn.Open(); NpgsqlCommand pgcom = new NpgsqlCommand(sql3, conn); pgcom.CommandType = CommandType.StoredProcedure; // 修正参数名与类型 pgcom.Parameters.AddWithValue("orderdate", NpgsqlTypes.NpgsqlDbType.Date, DateTime.Parse("2022-01-01")); NpgsqlDataReader pgreader = pgcom.ExecuteReader(); while (pgreader.Read()) { // 修正索引 int albumCount = pgreader.GetInt32(0); int month = pgreader.GetInt32(1); // 添加后续业务逻辑 } // 记得释放资源 pgreader.Close(); conn.Close(); return View(); // 或返回对应结果集 }
内容的提问来源于stack exchange,提问作者Rahul Patil
相关产品推荐
相关产品推荐

