C#和PostgreSQL
有人能给我举一个使用从PLSQL返回到C代码的游标的工作示例吗 我找到了许多示例,展示了如何用返回的数据填充C#和PostgreSQL,c#,.net,sql,postgresql,ado.net,C#,.net,Sql,Postgresql,Ado.net,有人能给我举一个使用从PLSQL返回到C代码的游标的工作示例吗 我找到了许多示例,展示了如何用返回的数据填充数据集,但我找不到如何将光标与数据读取器一起使用,因此我得到了{unnamed portal} NpgsqlTransaction tr = (NpgsqlTransaction) Connection.BeginTransaction(); NpgsqlCommand cursCmd = new NpgsqlCommand("someStoredProcedure(:inRadius)"
数据集
,但我找不到如何将光标与数据读取器
一起使用,因此我得到了{unnamed portal}
NpgsqlTransaction tr = (NpgsqlTransaction) Connection.BeginTransaction();
NpgsqlCommand cursCmd = new NpgsqlCommand("someStoredProcedure(:inRadius)", (NpgsqlConnection) Connection);
cursCmd.Transaction = tr;
NpgsqlParameter rf = new NpgsqlParameter("ref", NpgsqlTypes.NpgsqlDbType.Refcursor);
rf.Direction = ParameterDirection.InputOutput;
cursCmd.Parameters.Add(rf);
我必须添加这个来使用NpgsqlDataReader-myReader代码>正确:
tr.Commit();
当我在sql命令之后编写fetch
时,它可以工作,但不适用。首先,这里是一些有用的文档:
在本文档中,您可以找到一个NpgsqlDataAdapter
。此对象还有一个Fill()
方法(继承自DbDataAdapter
)。此方法可以使用数据集
和光标。它将用光标返回的数据填充数据集
你实际上不能给这个方法一个DataReader
,但是你可以给一个DataTable
,我想你可以用它做点什么。我对我的问题有一些答案
问题:我有一个存储的PLSQL过程,它返回refCursor
。我必须使用DataReader
获取返回的数据,但是当我添加参数时,db返回了
要遍历所有返回的数据,我必须这样编写代码:
NpgsqlTransaction tr = (NpgsqlTransaction) Connection.BeginTransaction();
NpgsqlCommand cursCmd = new NpgsqlCommand("someStoredProcedure", (NpgsqlConnection) Connection);
cursCmd.Transaction = tr;
NpgsqlParameter rf = new NpgsqlParameter("ref", NpgsqlTypes.NpgsqlDbType.Refcursor);
rf.Direction = ParameterDirection.InputOutput;
cursCmd.Parameters.Add(rf);
NpgsqlParameter param2 = new NpgsqlParameter("param1", NpgsqlTypes.Int32);
rf.Direction = ParameterDirection.Input;
cursCmd.Parameters.Add(param2);
NpgsqlDataReader r = cmd.ExecuteReader();
while (r.Read())
{
; // r.GetValue(0);
}
r.NextResult();
while(r.Read())
{
;
}
tr.Commit();
请注意,您不会像func(:param1)
那样在sql中编写参数
如果函数中有参数,请仅将函数名指定给CommandText
属性,并像往常一样将参数添加到NpgsqlCommand.parameters
集合中。Npgsql将负责正确绑定您的参数
但现在我有另一个问题。当我将另一个输出参数传递给我的CommandText
时,结果中有两个字段。其中一个是0{my first output param}
,另一个是
在Oracle中,我可以直接将RefCursor
参数转换为DataReader
,但在postgresql中,我不能。通过在同一事务中使用两个命令,我解决了Out
参数的问题
在第一个命令中,我读取out参数,然后执行下一个命令
第二个命令如下所示:
var cmd2 = new NpgsqlCommand("FETCH ALL FROM \"list\"", (NpgsqlConnection) Connection)
其中list
在存储过程中创建的游标的名称。因此,我从数据库中选择了数据。供您参考:
/// <summary>
/// Get data from the returning refcursor of postgresql function
/// </summary>
/// <param name="FunctionName">Function name of postgresql</param>
/// <param name="Parameters">parameters to pass to the postgresql function</param>
/// <param name="ErrorOccured">out bool parameter to check if it occured error</param>
/// <returns></returns>
public List<DataTable> GetRefCursorData(string FunctionName, List<object> Parameters, out bool ErrorOccured)
{
string connectstring = ""; //your connectstring here
List<DataTable > dtRtn =new List<DataTable>();
NpgsqlConnection connection = null;
NpgsqlTransaction transaction = null;
NpgsqlCommand command = null;
try
{
connection = new NpgsqlConnection(connectstring);
transaction = connection.BeginTransaction();
command = new NpgsqlCommand();
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = FunctionName;
command.Transaction = transaction;
//
if (Parameters != null)
{
foreach (object item in Parameters)
{
NpgsqlParameter parameter = new NpgsqlParameter();
parameter.Direction = ParameterDirection.Input;
parameter.Value = item;
command.Parameters.Add(parameter);
}
}
//
NpgsqlDataReader dr = command.ExecuteReader();
while (dr.Read())
{
DataTable dt = new DataTable();
command = new NpgsqlCommand("FETCH ALL IN " + "\"" + dr[0].ToString() + "\"", Connection); //use plpgsql fetch command to get data back
NpgsqlDataAdapter da = new NpgsqlDataAdapter(command);
da.Fill(dt);
dtRtn.Add(dt); //all the data will save in the List<DataTable> ,no matter the connection is closed or returned multiple refcursors
}
ErrorOccured = false;
transaction.Commit();
}
catch
{
//error handling ...
ErrorOccured = true;
if (transaction != null) transaction.Rollback();
}
finally
{
if (connection != null) connection.Close();
}
return dtRtn;
}
//
///从postgresql函数返回的refcursor获取数据
///
///postgresql的函数名
///要传递给postgresql函数的参数
///out bool参数检查是否发生错误
///
公共列表GetRefCursorData(字符串函数名,列表参数,发生out bool错误)
{
string connectstring=”“;//此处是您的connectstring
List dtRtn=新列表();
NpgsqlConnection=null;
NpgsqlTransaction=null;
NpgsqlCommand=null;
尝试
{
连接=新的NpgsqlConnection(connectstring);
事务=连接。BeginTransaction();
command=新的NpgsqlCommand();
command.Connection=连接;
command.CommandType=CommandType.storedProcess;
command.CommandText=函数名;
command.Transaction=事务;
//
if(参数!=null)
{
foreach(参数中的对象项)
{
NpgsqlParameter=新的NpgsqlParameter();
parameter.Direction=ParameterDirection.Input;
参数值=项目;
command.Parameters.Add(参数);
}
}
//
NpgsqlDataReader dr=command.ExecuteReader();
while(dr.Read())
{
DataTable dt=新的DataTable();
command=new NpgsqlCommand(“在“+”\”“+dr[0].ToString()+“\”“,Connection中提取所有数据”);//使用plpgsql FETCH命令获取数据
NpgsqlDataAdapter da=新的NpgsqlDataAdapter(命令);
da.填充(dt);
dtRtn.Add(dt);//所有数据都将保存在列表中,无论连接是否关闭或返回多个引用游标
}
ErrorOccursed=false;
Commit();
}
抓住
{
//错误处理。。。
ErrorOccursed=true;
if(transaction!=null)transaction.Rollback();
}
最后
{
if(connection!=null)connection.Close();
}
返回dtRtn;
}
我认为这是一个相当具体的问题。当您提供函数的示例调用时,这个答案会更有用。例如,我们应该如何初始化列表参数?这一行执行da.Fill(dt)时出现错误“一个命令已经在执行中”;