PostgreSql 使用多个结果集调用存储过程

时间:2021-03-08 13:47:46

标签: c# postgresql stored-procedures npgsql

我正在将 MSSQL 数据库迁移到 PostgreSql。 MSSQL db 有一个返回多个结果集的存储过程。为了将其迁移到 Postgres,我将 refcursors 作为参数传入以检索多个结果集,例如

CREATE OR REPLACE PROCEDURE public.test_proc(IN par_id bigint, INOUT ref_cur1 refcursor, INOUT ref_cur2 refcursor)
    LANGUAGE 'plpgsql'
    
AS $BODY$
BEGIN
    OPEN ref_cur1 FOR
    SELECT * From firsttable where firsttable.id = par_id;
    OPEN ref_cur2 FOR
    SELECT * from secondtable where lnkid = par_id;
END;
$BODY$;

我正在尝试使用 Npgsql 在我的 .net 应用程序中调用该存储过程

using (var lConn = GetConnection()) {
                    using (var trans = lConn.BeginTransaction()) {
                        using (var cmd = GetCommand("call public.test_proc(@par_id, @ref_cur1, @ref_cur2)", lConn, trans, System.Data.CommandType.Text)) {
                            cmd.Parameters.Add("@par_id", NpgsqlDbType.Integer).Value = id;
                            cmd.Parameters.Add(new NpgsqlParameter() {
                                ParameterName = "@ref_cur1",
                                NpgsqlDbType = NpgsqlDbType.Refcursor,
                                Value = "ref_cur1",
                                Direction = System.Data.ParameterDirection.InputOutput
                            });

                            cmd.Parameters.Add(new NpgsqlParameter() {
                                ParameterName = "@ref_cur2",
                                NpgsqlDbType = NpgsqlDbType.Refcursor,
                                Value = "ref_cur2",
                                Direction = System.Data.ParameterDirection.InputOutput
                            });

                            cmd.ExecuteNonQuery();

                            cmd.CommandText = $"fetch all \"ref_cur1\"";
                            cmd.CommandType = CommandType.Text;
                            var reader = cmd.ExecuteReader();

                            if (reader.HasRows)
                            {
                                while (reader.Read())
                                {
                                    string name = (string)reader["name"];
                                    DateTime dtTime = (DateTime)reader["createddate"];
                                }
                            }

                            reader.Close();

                            cmd.CommandText = $"fetch all \"ref_cur2\"";
                            cmd.CommandType = CommandType.Text;
                            reader = cmd.ExecuteReader(); //This throws exception

                            if (reader.HasRows)
                            {
                                while (reader.Read())
                                {
                                    string name = (string)reader["description"];
                                    int lnkId = (int)reader["lnkid"];
                                }
                            }
                            reader.Close();

                        }
                    }
                }

我能够读取 ref_cur1 的值,但在尝试检索第二个光标时出现以下异常

<块引用>

无法使用处理程序类型 TextHandler 编写 CLR 类型 System.Int64

我是 postgres 的新手,上面的大部分 sql 和代码来自不同的谷歌搜索,所以如果有更好的方法从 SP 返回多个结果,请告诉我。

1 个答案:

答案 0 :(得分:0)

我无法使用存储过程进行处理,因此最终恢复使用函数,为此相同的 Npgsql 代码成功获取了多个游标。我唯一需要做的改变就是使用

<块引用>

var cmd = GetCommand("public.test_proc"

用于函数而不是

<块引用>

var cmd = GetCommand("调用 public.test_proc(@par_id, @ref_cur1, @ref_cur2)"

用于存储过程

感谢@ShayRojansky 的协助。