Npgsql调用PostgreSQL存储过程提示‘procedure does not exist’求助
解决Npgsql调用PostgreSQL存储过程报错42883的问题
错误42883: procedure shipment_status.updatefilelocation() does not exist的核心原因是你调用的是无参版本的存储过程,但实际创建的是带4个参数的版本,PostgreSQL无法匹配到对应的存储过程签名。以下是具体修复方案:
修复步骤
1. 修正CALL语句,匹配存储过程参数签名
你的C#代码中CALL shipment_status.updatefilelocation()是无参调用,但存储过程需要4个参数,必须在CALL语句中明确参数占位符,两种写法可选:
方式一:位置占位符(按参数顺序匹配)
var cmd = new NpgsqlCommand("CALL shipment_status.updatefilelocation($1, $2, $3, $4)", con);
方式二:命名参数(更清晰,避免顺序错误)
var cmd = new NpgsqlCommand("CALL shipment_status.updatefilelocation(ids_to_update => $1, files_to_update => $2, start_with => $3, end_with => $4)", con);
2. 确保参数传递准确
你的参数添加顺序是正确的(uuid数组 → text数组 → int → int),可以显式指定参数名称增强可读性:
cmd.Parameters.AddWithValue("ids_to_update", NpgsqlDbType.Array | NpgsqlDbType.Uuid, rfi.Ids.ToArray()); cmd.Parameters.AddWithValue("files_to_update", NpgsqlDbType.Array | NpgsqlDbType.Text, rfi.RawDataStorageLinks.ToArray()); cmd.Parameters.AddWithValue("start_with", NpgsqlDbType.Integer, 0); cmd.Parameters.AddWithValue("end_with", NpgsqlDbType.Integer, rfi.Ids.Count - 1);
3. 移除不必要的.ToLower()调用
PostgreSQL对未加引号的小写标识符不区分大小写,你的存储过程名称是小写的,无需将CALL语句转成小写,避免潜在的意外问题。
4. 验证权限与Schema可见性
确保执行代码的数据库用户拥有shipment_status Schema的访问权限,以及调用该存储过程的权限,可通过以下SQL配置:
GRANT USAGE ON SCHEMA shipment_status TO your_db_user; GRANT EXECUTE ON PROCEDURE shipment_status.updatefilelocation(uuid[], text[], integer, integer) TO your_db_user;
完整修复后的C#代码示例
NpgsqlConnection? con = null; try { RawFileInfo rfi = CreateRawFileInfo(blobData); if (rfi == null || rfi.Ids.Count == 0) return; con = new NpgsqlConnection(postgresConnection); con.Open(); var cmd = new NpgsqlCommand("CALL shipment_status.updatefilelocation(ids_to_update => $1, files_to_update => $2, start_with => $3, end_with => $4)", con); cmd.Parameters.AddWithValue("ids_to_update", NpgsqlDbType.Array | NpgsqlDbType.Uuid, rfi.Ids.ToArray()); cmd.Parameters.AddWithValue("files_to_update", NpgsqlDbType.Array | NpgsqlDbType.Text, rfi.RawDataStorageLinks.ToArray()); cmd.Parameters.AddWithValue("start_with", NpgsqlDbType.Integer, 0); cmd.Parameters.AddWithValue("end_with", NpgsqlDbType.Integer, rfi.Ids.Count - 1); int result = cmd.ExecuteNonQuery(); } catch (Exception ex) { // 补充你的异常处理逻辑 } finally { con?.Close(); }
额外注意点
存储过程中的COMMIT:如果你的C#代码默认使用自动提交模式,存储过程内的COMMIT会正常执行;但如果代码中显式开启了事务,存储过程内的COMMIT会抛出错误,此时需要移除存储过程中的COMMIT,由应用层统一控制事务。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

