Как я могу получить несколько результатов с помощью функции postgresql - PullRequest
0 голосов
/ 01 июня 2018

Я хочу вернуть несколько результатов с помощью функции.Но 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 голосов
/ 01 июня 2018

Использование setof refcursor - это способ эмулировать несколько наборов результатов в PG.Но на самом деле это не то же самое, что множественные результирующие наборы.

Npgsql, используемый для автоматической выборки содержимого курсоров, возвращаемых из хранимых процедур, но это также не всегда ожидалось, поэтому он был удален.Прочитайте всю (долгую) дискуссию на этой проблеме github .

В любом случае, чтобы получить данные, вы должны выполнить FETCH ALL FROM "<unnamed portal 1>" - где unnamed portal 1 должна быть строкой, возвращенной из сохраненногоProc.Курсоры останутся в живых достаточно долго, если вы выполните хранимую процедуру внутри транзакции.

Вы можете посмотреть, как Npgsql делал это здесь , или следовать общему подходу ниже:

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
            }
        }
    }
}
...