代码之家  ›  专栏  ›  技术社区  ›  Yevhen

C#和PostgreSQL

  •  2
  • Yevhen  · 技术社区  · 15 年前

    有人能给我举一个使用从PLSQL返回到C代码的游标的工作示例吗?

    dataSet 返回数据,但我找不到如何将该游标与 DataReader {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();
    

    当我写 fetch 在sql命令之后,它可以工作,但不适合。

    4 回复  |  直到 5 年前
        1
  •  4
  •   CarenRose    5 年前

    供参考:

    /// <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;
    }
    
        2
  •  1
  •   CarenRose    5 年前

    问题:我有一个存储的PLSQL过程,它返回 refCursor . 我必须使用 DataReader ,但当我添加参数时,数据库返回 <unnamed portal> .

    要遍历所有返回的数据,我必须这样编写代码:

    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();
    

    请注意,您不会像编写sql一样编写参数 func(:param1) .

    如果函数中有参数,请仅将函数名指定给 CommandText NpgsqlCommand.Parameters 像往常一样收集。Npgsql将负责正确绑定您的参数。

    但现在我有另一个问题。当我将另一个输出参数传递给 ,我的结果中有两个字段。其中之一是 0{my first output param} 另一个是 <未命名门户> .

    在Oracle中,我可以直接转换 RefCursor 参数设置为 ,但在postgresql中,我不能。

        3
  •  0
  •   CarenRose    5 年前

    Npgsql doc

    在本文档中,您将发现 NpgsqlDataAdapter . 此对象还具有 Fill() 方法(继承自 DbDataAdapter DataSet 和一个光标。会的 填满 这个 数据集

    你不能真的给出一个答案 DataReader 对于这种方法,您可以给出一个 DataTable

        4
  •  0
  •   CarenRose    5 年前

    我已经用计算机解决了这个问题 Out 在同一事务中使用两个命令创建参数。

    第二个命令如下所示:

    var cmd2 = new NpgsqlCommand("FETCH ALL FROM \"list\"", (NpgsqlConnection) Connection)
    

    哪里 list 在存储过程中创建的游标的名称。因此,我从数据库中选择了数据。