.NET向PostgreSQL函数传可选参数触发42883函数不存在错误
解决PostgreSQL函数在.NET中调用的42883错误(可选参数场景)
问题原因
当使用.NET的CommandType.StoredProcedure调用PostgreSQL函数时,驱动会按参数添加的顺序传递值,而PostgreSQL的函数匹配严格依赖参数的数量、类型和顺序。你跳过部分可选参数后,实际传递的参数列表与函数定义的签名不匹配,导致数据库找不到对应的函数,抛出42883: function does not exist错误。
解决方案
方案1:使用命名参数调用(推荐)
放弃CommandType.StoredProcedure,直接编写SQL调用语句,通过参数名 := 参数值的方式明确指定参数,这样无需严格遵循顺序,缺失的参数自动使用函数定义的默认值。
示例代码:
// 动态拼接带命名参数的SQL语句 var sqlBuilder = new StringBuilder("SELECT MyFunction("); sqlBuilder.Append("ip_No := @ip_No, ip_Id := @ip_Id, ip_Status := @ip_Status, ip_Name := @ip_Name, ip_User := @ip_User"); if (!string.IsNullOrWhiteSpace(Res)) sqlBuilder.Append(", ip_Res := @ip_Res"); if (!string.IsNullOrWhiteSpace(Super)) sqlBuilder.Append(", ip_Super := @ip_Super"); sqlBuilder.Append(", ip_Days := @ip_Days, ip_Pit := @ip_Pit, ip_Types := @ip_Types, ip_Description := @ip_Description"); if (!string.IsNullOrWhiteSpace(Possible)) sqlBuilder.Append(", ip_Possible := @ip_Possible"); if (Secondary != 0) sqlBuilder.Append(", ip_Secondary := @ip_Secondary"); if (!string.IsNullOrWhiteSpace(SecondaryRes)) sqlBuilder.Append(", ip_SecondaryRes := @ip_SecondaryRes"); sqlBuilder.Append(", ip_Overall := @ip_Overall, ip_Date := @ip_Date"); if (TargetDate != null) sqlBuilder.Append(", ip_TargetDate := @ip_TargetDate"); if (CompleteTargetDate != null) sqlBuilder.Append(", ip_CompleteTargetDate := @ip_CompleteTargetDate"); sqlBuilder.Append(", ip_CreatedBy := @ip_CreatedBy);"); cmd.CommandText = sqlBuilder.ToString(); cmd.CommandType = CommandType.Text; // 添加所有需要的参数 cmd.Parameters.AddWithValue("@ip_No", No); cmd.Parameters.AddWithValue("@ip_Id", Id); cmd.Parameters.AddWithValue("@ip_Status", Status); cmd.Parameters.AddWithValue("@ip_Name", Name); cmd.Parameters.AddWithValue("@ip_User", User); if (!string.IsNullOrWhiteSpace(Res)) cmd.Parameters.AddWithValue("@ip_Res", Res); if (!string.IsNullOrWhiteSpace(Super)) cmd.Parameters.AddWithValue("@ip_Super", Super); cmd.Parameters.AddWithValue("@ip_Days", Days); cmd.Parameters.AddWithValue("@ip_Pit", Pit); cmd.Parameters.AddWithValue("@ip_Types", Types); cmd.Parameters.AddWithValue("@ip_Description", Description); if (!string.IsNullOrWhiteSpace(Possible)) cmd.Parameters.AddWithValue("@ip_Possible", Possible); if (Secondary != 0) cmd.Parameters.AddWithValue("@ip_Secondary", Secondary); if (!string.IsNullOrWhiteSpace(SecondaryRes)) cmd.Parameters.AddWithValue("@ip_SecondaryRes", SecondaryRes); cmd.Parameters.AddWithValue("@ip_Overall", Overall); cmd.Parameters.AddWithValue("@ip_Date", Date); if (TargetDate != null) cmd.Parameters.AddWithValue("@ip_TargetDate", TargetDate); if (CompleteTargetDate != null) cmd.Parameters.AddWithValue("@ip_CompleteTargetDate", CompleteTargetDate); cmd.Parameters.AddWithValue("@ip_CreatedBy", CreatedBy); return ExecuteNonQuery(cmd) > 0;
方案2:传递所有参数(包括可选参数的默认值)
如果坚持使用CommandType.StoredProcedure,必须严格按照函数定义的参数顺序添加所有参数,可选参数无值时传递与函数定义一致的默认值(如DBNull.Value对应null,0对应默认整数等)。
示例代码片段:
cmd.CommandText = "MyFunction"; cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add(cmd.CreateParameter("ip_No", No)); cmd.Parameters.Add(cmd.CreateParameter("ip_Id", Id)); cmd.Parameters.Add(cmd.CreateParameter("ip_Status", Status)); cmd.Parameters.Add(cmd.CreateParameter("ip_Name", Name)); cmd.Parameters.Add(cmd.CreateParameter("ip_User", User)); // 可选参数无值时传递默认值 cmd.Parameters.Add(cmd.CreateParameter("ip_Res", string.IsNullOrWhiteSpace(Res) ? (object)DBNull.Value : Res)); cmd.Parameters.Add(cmd.CreateParameter("ip_Super", string.IsNullOrWhiteSpace(Super) ? (object)DBNull.Value : Super)); cmd.Parameters.Add(cmd.CreateParameter("ip_Days", Days)); // 后续所有参数按顺序添加,无值时传递对应默认值 // ...
内容的提问来源于stack exchange,提问作者elpidaguy
相关产品推荐
相关产品推荐

