System.NotSupportedException: 具有多个查询的命令不能有 out 参数
System.NotSupportedException: Commands with multiple queries cannot have out parameters
我 运行 遇到另一个问题,即在带有多个引用游标的存储过程周围使用数据 reader。我收到一个不受支持的异常。不幸的是,我可以从 npgsql 的源代码中看到它的来源,但是..我不确定我是否同意抛出该异常。我们编写的代码适用于 oracle(完全托管和托管类型),sql 服务器。感谢任何帮助使它在 api 的某些关键 dbms 风格中保持一致。
存储过程体
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$;
关键 Reader 包装 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 参数的代码是这样的
您上面的代码似乎使 PostgreSQL 函数与试图读取其结果的 .NET 客户端代码混淆。
无论如何,您的函数被声明为 return 一组 组 refcursors - 这与两个输出参数不同;您似乎混淆了游标的名称(例如,游标有名称,但没有整数)与 参数 的名称(int 参数确实有名称)。
请注意 PostgreSQL 实际上没有输出参数 - 函数总是 return 一个 table,仅此而已。 PostgreSQL 确实有带输出参数的函数语法,但这只是构造输出模式 table 的一种方式。这与 SQL 服务器不同,它显然可以 return 同时具有 table 和 一组命名输出参数。为了促进可移植性,在读取结果时,如果 Npgsql 看到任何方向为 out 的 NpgsqlParameter,它将尝试查找具有参数名称的结果集,并将简单地使用该列第一行的值填充 NpgsqlParameter 的值。与简单地自己阅读结果集相比,这种做法的附加值为零 - 它只是为了兼容性。
总而言之,我建议您使用 reader 阅读 refcursors,然后适当地获取它们的结果。
我 运行 遇到另一个问题,即在带有多个引用游标的存储过程周围使用数据 reader。我收到一个不受支持的异常。不幸的是,我可以从 npgsql 的源代码中看到它的来源,但是..我不确定我是否同意抛出该异常。我们编写的代码适用于 oracle(完全托管和托管类型),sql 服务器。感谢任何帮助使它在 api 的某些关键 dbms 风格中保持一致。
存储过程体
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$;
关键 Reader 包装 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 参数的代码是这样的
您上面的代码似乎使 PostgreSQL 函数与试图读取其结果的 .NET 客户端代码混淆。
无论如何,您的函数被声明为 return 一组 组 refcursors - 这与两个输出参数不同;您似乎混淆了游标的名称(例如,游标有名称,但没有整数)与 参数 的名称(int 参数确实有名称)。
请注意 PostgreSQL 实际上没有输出参数 - 函数总是 return 一个 table,仅此而已。 PostgreSQL 确实有带输出参数的函数语法,但这只是构造输出模式 table 的一种方式。这与 SQL 服务器不同,它显然可以 return 同时具有 table 和 一组命名输出参数。为了促进可移植性,在读取结果时,如果 Npgsql 看到任何方向为 out 的 NpgsqlParameter,它将尝试查找具有参数名称的结果集,并将简单地使用该列第一行的值填充 NpgsqlParameter 的值。与简单地自己阅读结果集相比,这种做法的附加值为零 - 它只是为了兼容性。
总而言之,我建议您使用 reader 阅读 refcursors,然后适当地获取它们的结果。