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

时间:2017-12-25 15:58:50

标签: npgsql

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

sproc body

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参数的代码就是这样的

1 个答案:

答案 0 :(得分:0)

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

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

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

总结一下,我建议您与读者一起阅读反馈器,然后根据需要获取结果。