是否可以将 refcursor 作为参数直接传递给 Npgsql 上的 FETCH?
Is it possible to pass a refcursor as a parameter directly to FETCH on Npgsql?
在对 PostgreSQL 使用 Npgsql 库时,我找不到任何方法将游标引用作为参数传递给 FETCH
命令。这可能吗?
using (DbConnection connection = new NpgsqlConnection(connectionString))
{
connection.Open();
using (DbTransaction transaction = connection.BeginTransaction())
{
var outCursor = new NpgsqlParameter("cursor", NpgsqlTypes.NpgsqlDbType.Refcursor);
outCursor.Direction = ParameterDirection.Output;
// get a refcursor from somewhere
using (DbCommand commandGet = connection.CreateCommand())
{
commandGet.CommandText = "get_cursor";
commandGet.CommandType = CommandType.StoredProcedure;
commandGet.Parameters.Add(outCursor);
commandGet.Connection = connection;
commandGet.ExecuteNonQuery();
}
// try to use it
using (DbCommand commandFetch = connection.CreateCommand())
{
var inCursor = new NpgsqlParameter("cursor", NpgsqlTypes.NpgsqlDbType.Refcursor);
inCursor.Direction = ParameterDirection.Input;
inCursor.Value = outCursor.Value;
// This commented out line using string interpolation works fine.
// Can it be done with a parameter, as I'm trying to do below?
//commandFetch.CommandText = $"FETCH 100 FROM \"{outCursor.Value}\"";
// The same inCursor pattern used here works fine when the cursor is being passed
// on to a function, but does not work for FETCH
commandFetch.CommandText = $"FETCH 100 FROM :cursor";
commandFetch.Parameters.Add(inCursor);
commandFetch.Connection = connection;
// This line fails for param-based version;
// works fine with string-interpolation version
using (var reader = commandFetch.ExecuteReader())
{
while (reader.Read())
{
int a = (int)reader[0];
}
}
}
// close it
using (DbCommand commandClose = connection.CreateCommand())
{
// I would like to be able to pass the cursor as a true parameter here, too
commandClose.CommandText = $"CLOSE \"{outCursor.Value}\"";
commandClose.Connection = connection;
var reader = commandClose.ExecuteNonQuery();
}
}
}
注意注释掉的行:我可以让代码工作,我只是想找到一种方法让它工作,将游标引用作为参数传回。
我得到的异常是 Npgsql.PostgresException : 42601: syntax error at or near ""
。
传递纯字符串值参数(看起来可能有效...)也失败,但有相同的异常。
如果将输入游标传递给函数,上述用于从输出游标创建输入游标的模式工作正常。
由于底层数据库的限制。
you cannot use a variable in a FETCH statement. Use dynamic SQL: EXECUTE format('FETCH ALL FROM %I', foo);
所以这不是 Npgsql 的限制,其他答案中建议的解决方法也可以应用于 Npgsql。或者,您可以将字符串插入 SQL,尽管在某种程度上 'ugly'(至少在我看来)实际上是完全安全的。
(在这种情况下 - 但将值直接插入 SQL 通常是一个坏主意,至少没有第二和第三次思考为什么,甚至在任何给定的限制 use-case 中在所有可能的情况下都可以安全地抵御注入攻击。)
在对 PostgreSQL 使用 Npgsql 库时,我找不到任何方法将游标引用作为参数传递给 FETCH
命令。这可能吗?
using (DbConnection connection = new NpgsqlConnection(connectionString))
{
connection.Open();
using (DbTransaction transaction = connection.BeginTransaction())
{
var outCursor = new NpgsqlParameter("cursor", NpgsqlTypes.NpgsqlDbType.Refcursor);
outCursor.Direction = ParameterDirection.Output;
// get a refcursor from somewhere
using (DbCommand commandGet = connection.CreateCommand())
{
commandGet.CommandText = "get_cursor";
commandGet.CommandType = CommandType.StoredProcedure;
commandGet.Parameters.Add(outCursor);
commandGet.Connection = connection;
commandGet.ExecuteNonQuery();
}
// try to use it
using (DbCommand commandFetch = connection.CreateCommand())
{
var inCursor = new NpgsqlParameter("cursor", NpgsqlTypes.NpgsqlDbType.Refcursor);
inCursor.Direction = ParameterDirection.Input;
inCursor.Value = outCursor.Value;
// This commented out line using string interpolation works fine.
// Can it be done with a parameter, as I'm trying to do below?
//commandFetch.CommandText = $"FETCH 100 FROM \"{outCursor.Value}\"";
// The same inCursor pattern used here works fine when the cursor is being passed
// on to a function, but does not work for FETCH
commandFetch.CommandText = $"FETCH 100 FROM :cursor";
commandFetch.Parameters.Add(inCursor);
commandFetch.Connection = connection;
// This line fails for param-based version;
// works fine with string-interpolation version
using (var reader = commandFetch.ExecuteReader())
{
while (reader.Read())
{
int a = (int)reader[0];
}
}
}
// close it
using (DbCommand commandClose = connection.CreateCommand())
{
// I would like to be able to pass the cursor as a true parameter here, too
commandClose.CommandText = $"CLOSE \"{outCursor.Value}\"";
commandClose.Connection = connection;
var reader = commandClose.ExecuteNonQuery();
}
}
}
注意注释掉的行:我可以让代码工作,我只是想找到一种方法让它工作,将游标引用作为参数传回。
我得到的异常是 Npgsql.PostgresException : 42601: syntax error at or near ""
。
传递纯字符串值参数(看起来可能有效...)也失败,但有相同的异常。
如果将输入游标传递给函数,上述用于从输出游标创建输入游标的模式工作正常。
you cannot use a variable in a FETCH statement. Use dynamic SQL: EXECUTE format('FETCH ALL FROM %I', foo);
所以这不是 Npgsql 的限制,其他答案中建议的解决方法也可以应用于 Npgsql。或者,您可以将字符串插入 SQL,尽管在某种程度上 'ugly'(至少在我看来)实际上是完全安全的。
(在这种情况下 - 但将值直接插入 SQL 通常是一个坏主意,至少没有第二和第三次思考为什么,甚至在任何给定的限制 use-case 中在所有可能的情况下都可以安全地抵御注入攻击。)