System.NotSupportedException:具有多个查询的命令不能具有out参数

问题描述 投票:0回答:1

我遇到了另一个问题,即使用带有多个ref游标的sproc周围的数据读取器。我得到一个不受支持的例外。不幸的是,我可以从npgsql的源代码中看到它来自哪里..我不确定我是否同意抛出该异常。我们编写的代码与oracle(完全托管和托管的版本),sql server一起使用。任何帮助都会受到赞赏,以保持它与某些关键的dbms风格的api保持一致。

sproc身体

CREATE OR REPLACE FUNCTION public.getmultipleresultsets (
    v_organizationid integer)
    RETURNS Setof refcursor
    LANGUAGE 'plpgsql'

AS $BODY$

declare       public override void AddCursorOutParameter(DbCommand command,
        string RefCursorName)
    { 
        NpgsqlParameter parameter = (NpgsqlParameter)CreateParameter(RefCursorName, false);
        parameter.NpgsqlDbType = NpgsqlDbType.Refcursor;
        parameter.NpgsqlValue = DBNull.Value;
        parameter.Direction = ParameterDirection.Output;

        command.Parameters.Add(parameter); 
    }
cv_1 refcursor;
cv_2 refcursor;

BEGIN 

    open cv_1 for
    SELECT a.errorCategoryId, a.name, a.bitFlag
    FROM ErrorCategories a
    ORDER BY name;
    RETURN next cv_1;

    open cv_2 for
    SELECT * 
    FROM StgNetworkStats  ;
    RETURN next cv_2;

END;

$BODY$;

包装postgres sql的密钥阅读器代码(npgsql的Entlib实现)

private IDataReader DoExecuteReader(DbCommand command, CommandBehavior cmdBehavior)
{
    try
    {

        var sql = new StringBuilder();

        using (var reader = command.ExecuteReader(CommandBehavior.SequentialAccess))
        {
            while (reader.Read())
            {
                sql.AppendLine($"FETCH ALL IN \"{ reader.GetString(0) }\";");
            }
        }

        command.CommandText = sql.ToString();
        command.CommandType = CommandType.Text; 

        IDataReader reader2 = command.ExecuteReader(cmdBehavior);
        return reader2;

    }
    catch (Exception)
    {
        throw;
    }
}

命令构建代码如下所示

 Helper.InitializeCommand(cmd, 300, "getmultipleresultsets");
    db.AddReturnValueParameter(cmd);

    db.AddInParameter(cmd, "organizationId", DbType.Int32, ORGANIZATIONID);

    db.AddCursorOutParameter(cmd, "CV_1");
    db.AddCursorOutParameter(cmd, "CV_2

添加refcursor参数的代码就是这样的

npgsql
1个回答
0
投票

您上面的代码似乎使用.NET客户端代码尝试读取其结果时使PostgreSQL函数变得混乱。

无论如何,您的函数被声明为返回一组refcursors - 这与两个输出参数不同;你似乎混淆了游标的名称(游标有名字,但不是int,例如)和参数的名称(int参数确实有名字)。

请注意,PostgreSQL实际上没有输出参数 - 函数总是返回一个表,就是这样。 PostgreSQL确实有一个带输出参数的函数语法,但这只是构造输出表模式的一种方法。这与SQL Server不同,后者显然可以返回表和一组命名输出参数。为了便于移植,在读取结果时,如果Npgsql看到任何带有方向输出的NpgsqlParameter,它将尝试查找带有参数名称的结果集,并只使用该列的第一行值填充NpgsqlParameter的Value。这种做法与简单地自己阅读结果集相比没有增值 - 它只是为了兼容性。

总结一下,我建议你用读者阅读refcursors,然后根据需要获取结果。

© www.soinside.com 2019 - 2024. All rights reserved.