如何使用postgresql函数获得多结果集

时间:2018-06-01 12:12:11

标签: c# postgresql npgsql

我想用函数返回多个结果集。但是reader.NextResult()不起作用。查询结果如下

"<unnamed portal 1>"
"<unnamed portal 2>"

功能(存储过程),PostgreSQL

CREATE OR REPLACE FUNCTION public.sp_get_multiviewlist
( )
RETURNS SETOF refcursor
DECLARE
    ref1 refcursor;
    ref2 refcursor;
BEGIN
OPEN ref1 FOR
SELECT * FROM public."Customer";
RETURN NEXT ref1;

OPEN ref2 FOR 
SELECT * FROM public."Order";
RETURN NEXT ref2;

END;

$$ LANGUAGE plpgsql;

其他数据库正常运行。我该怎么办?

npgsql:ver 3.2.5

1 个答案:

答案 0 :(得分:1)

使用setof refcursor是一种可以在PG中模拟多个结果集的方法。但它与多个结果集实际上并不相同。

Npgsql用于自动获取从存储过程返回的游标的内容,但这种情况并非总是如此,因此它被删除了。阅读this github issue处的整个(长期)讨论。

无论如何,要获取数据,必须执行FETCH ALL FROM "<unnamed portal 1>" - 其中unnamed portal 1必须是从存储过程返回的字符串。 如果在事务中执行存储过程,游标只能保持足够长的活动时间。

您可以查看Npgsql如何执行此操作here,或遵循以下常规方法:

using(var trans = db.BeginTransaction())
using(var cmd = db.CreateCommand()) {           
    cmd.CommandText = "sp_get_multiviewlist";
    cmd.CommandType = CommandType.StoredProcedure;  

    string cursor1Name,cursor2Name;
    using (var reader = cmd.ExecuteReader())
    {
        reader.Read();
        cursor1Name = reader.GetString(0);
        reader.Read();
        cursor2Name = reader.GetString(0);
    }


    using(var resultSet1 = db.CreateCommand())
    {
        resultSet1.CommandText = $@"FETCH ALL FROM ""{cursor1Name}""";
        using (var reader = resultSet1.ExecuteReader())
        {
            while (reader.Read())
            {
                // Do something with the customer row
            }
        }
    }

    using (var resultSet2 = db.CreateCommand())
    {
        resultSet2.CommandText = $@"FETCH ALL FROM ""{cursor2Name}""";
        using (var reader = resultSet2.ExecuteReader())
        {
            while (reader.Read()) {
                // Do something with the order row
            }
        }
    }
}