如何通过在npgsql中调用存储过程来获取游标数据

时间:2015-09-30 09:21:23

标签: c# npgsql

我已查看www.npgsql.org中的资料,但找不到如何解决我的问题......

表,PostgreSQL

[City], [State]
"Austin", "TX"
"Houston", "TX"
"Los Angeles", "CA"
"San Diego", "CA"
"San Fransisco";"CA"
"St.Louis", "MO"

功能(存储过程),PostgreSQL

-- Procedure that returns a single result set (cursor) 
   CREATE OR REPLACE FUNCTION show_cities() RETURNS refcursor AS $$
    DECLARE
      ref refcursor;
    BEGIN
      OPEN ref FOR SELECT city, state FROM cities;
      RETURN ref;                                 
    END;
    $$ LANGUAGE plpgsql;

代码,C#

using (NpgsqlConnection conn = new NpgsqlConnection(ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString))
{
    conn.Open();
    using (NpgsqlTransaction tran = conn.BeginTransaction())
    {
        using (var command = new NpgsqlCommand("show_cities", conn))
        {
            command.Transaction = tran;
            command.CommandType = CommandType.StoredProcedure;
            NpgsqlDataReader dr = command.ExecuteReader();

            while (dr.Read())
                str += dr.GetValue(0);

            dr.Close();
        }
        tran.Commit();
    }
}

这将返回“未命名的门户1”并且它是一个要获取的光标而不是数据, 有没有办法将其转换为奥斯汀,休斯顿,洛杉矶等数据?

互联网上有一些关于此的帖子,但我不确定我做错了什么。

  • npgsql:ver3.0.3
  • c#:vs2012

(添加) 我发现这是在npgsql ver3.x上发生的,而在ver2.x中它可以正常使用我的代码。获取光标的用法是否有任何变化?

(参考) http://www.sqlines.com/postgresql/npgsql_cs_result_sets

2 个答案:

答案 0 :(得分:10)

在Shay的帮助下,我弄清楚在删除“dereferenced”功能后我们如何在v3.x中获取光标。 我认为这方面没有太多好的例子,我希望这可以帮助人们节省搜索范例的时间。

您可以在npgsql ver3.x中执行此操作

<强> 1。 CommandType.StoredProcedure (未定义游标名称)

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 (已定义游标名称)

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 (已定义游标名称)

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

(参考v2.x)http://www.sqlines.com/postgresql/npgsql_cs_result_sets

这是一个易于理解的示例,因此如果您希望函数返回单个结果集,那么请考虑将其返回cursor作为@Shay建议或创建一个table。 {1}}不是@CeOnSql建议的view

谢谢!

答案 1 :(得分:6)

Npgsql 2.x有一个功能,可以自动&#34;取消引用&#34;游标从函数返回。此功能已从Npgsql 3.0中删除;这在我们的3.0迁移节点中提到,讨论在this issue。由于光标只是被返回而且没有被解除引用,所以Npgsql返回游标名称本身(未命名的门户1);您现在可以通过发送FETCH

来从此查询中获取结果

然而,如前所述,在函数中包装单个SELECT并没有多大意义。如果确实需要编写一个返回单个结果集的函数,请使其返回SETOF或TABLE而不是游标:CREATE FUNCTION ... RETURNS TABLE (column_name column_type [, ...])。除了更简单和更干净之外,这也更有效,因为查询结果是直接返回的(取消引用游标涉及另一个数据库往返)。

有关如何定义返回表格的函数的详细信息,请参阅PostgreSQL docs