how can I get cursor data with calling stored procedure in npgsql

后端 未结 3 529
清酒与你
清酒与你 2020-12-03 23:33

I have looked into materials in www.npgsql.org, but couldn\'t find how to solve my problem...

Table, PostgreSQL

[City], [State]
\"Au         


        
相关标签:
3条回答
  • 2020-12-03 23:59

    Npgsql 2.x had a feature whereby it automatically "dereferenced" cursors returned from functions. This feature was dropped from Npgsql 3.0; this is mentioned in our migration nodes for 3.0, and the discussion is in this issue. Since the cursor is simply returned and isn't dereferenced, Npgsql returns the cursor name itself (unnamed portal 1); you can now fetch results from this query by sending FETCH etc.

    However, as was mentioned, wrapping a single SELECT in a function doesn't make much sense. If you do need to write a function that returns a single resultset, make it return a SETOF or a TABLE instead of a cursor: CREATE FUNCTION ... RETURNS TABLE (column_name column_type [, ...]). Apart from being simpler and cleaner, this is also more efficient, as the query results are returned directly (dereferencing the cursor involves another database roundtrip).

    See the PostgreSQL docs for more info on how to define a function returning a table.

    0 讨论(0)
  • 2020-12-04 00:10

    I have following working code with Npgsql 2.2.7 version:

     private static DataSet ExecuteFunction(string functionName)
        {
            DataSet ds = new DataSet();
    
            var conn = new NpgsqlConnection("replace with connection string");
            conn.Open();
            var tran = conn.BeginTransaction();
            var cmd = new NpgsqlCommand(functionName, conn);
            cmd.CommandType = CommandType.StoredProcedure;
    
            NpgsqlDataAdapter da = new NpgsqlDataAdapter(cmd);
            da.Fill(ds);
    
            //foreach (DataRow r in ds.Tables[0].Rows)
            //{
            //    Console.WriteLine("{0}", r[0]);
            //}
    
            tran.Commit();
            conn.Close();
            return ds;
        }
    
    0 讨论(0)
  • 2020-12-04 00:15

    With Shay's help, I figured out how we can fetch cursor in v3.x after removal of "dereferenced" feature. I think there are not much of good example on this, I hope this might help people save time to search example.

    You can do this in npgsql ver3.x

    1. CommandType.StoredProcedure (cursor name not defined)

    conn.Open();
    NpgsqlTransaction tran = conn.BeginTransaction();
    
    NpgsqlCommand command = new NpgsqlCommand("show_cities", conn);
    command.CommandType = CommandType.StoredProcedure;
    command.ExecuteNonQuery();
    
    command.CommandText = "fetch all in \"<unnamed portal 1>\"";
    command.CommandType = CommandType.Text;
    
    NpgsqlDataReader dr = command.ExecuteReader();
    while (dr.Read())
    {
        // do what you want with data, convert this to json or...
        Console.WriteLine(dr[0]);
    }
    dr.Close();
    
    tran.Commit();
    conn.Close();
    

    2. CommandType.StoredProcedure (cursor name defined)

    conn.Open();
    NpgsqlTransaction tran = conn.BeginTransaction();
    
    NpgsqlCommand command = new NpgsqlCommand("select show_cities(@ref)", conn);
    command.CommandType = CommandType.Text;
    NpgsqlParameter p = new NpgsqlParameter();
    p.ParameterName = "@ref";
    p.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Refcursor;
    p.Direction = ParameterDirection.InputOutput;
    p.Value = "ref";
    command.Parameters.Add(p);
    command.ExecuteNonQuery();
    
    command.CommandText = "fetch all in \"ref\"";
    command.CommandType = CommandType.Text;
    
    NpgsqlDataReader dr = command.ExecuteReader();
    while (dr.Read())
    {
        // do what you want with data, convert this to json or...
        Console.WriteLine(dr[0]);
    }
    dr.Close();
    
    tran.Commit();
    conn.Close();
    

    3. CommandType.Text (cursor name defined)

    conn.Open();
    NpgsqlTransaction tran = conn.BeginTransaction();
    
    NpgsqlCommand command = new NpgsqlCommand("select show_cities(@ref)", conn);
    command.CommandType = CommandType.Text;
    NpgsqlParameter p = new NpgsqlParameter();
    p.ParameterName = "@ref";
    p.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Refcursor;
    p.Direction = ParameterDirection.InputOutput;
    p.Value = "ref";
    command.Parameters.Add(p);
    command.ExecuteNonQuery();
    
    command.CommandText = "fetch all in \"ref\"";
    command.CommandType = CommandType.Text;
    
    NpgsqlDataReader dr = command.ExecuteReader();
    while (dr.Read())
    {
        // do what you want with data, convert this to json or...
        Console.WriteLine(dr[0]);
    }
    dr.Close();
    
    tran.Commit();
    conn.Close();
    

    (reference for v2.x) http://www.sqlines.com/postgresql/npgsql_cs_result_sets

    This is example for easy understanding, so if you want your function to return single result set, then instead of returning cursor, please consider it to return table as @Shay suggested or create a view not a function as @CeOnSql suggested.

    Thanks !

    0 讨论(0)
提交回复
热议问题