如何在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”并且它是一个要获取的光标而不是数据,有没有办法将其转换为奥斯汀,休斯顿,洛杉矶……等数据

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

  • npgsql:ver3.0.3
  • c#:vs2012

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

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

Npgsql 2.x有一个function,它自动从函数返回“解引用”游标。 此function已从Npgsql 3.0中删除; 这在我们的3.0迁移节点中提到,讨论就在这个问题上 。 由于光标只是被返回而没有被解引用,因此Npgsql返回游标名称本身(未命名的门户1); 您现在可以通过发送FETCH等来从此查询中获取结果。

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

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

在Shay的帮助下,我想出了在删除“ dereferenced ”function后我们如何在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 \"\""; 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

这是易于理解的示例,因此如果您希望函数返回单个结果集,那么请考虑将其返回到@Shay建议的table ,或者创建view而不是@CeOnSql建议的function

谢谢 !

我有Npgsql 2.2.7版本的以下工作代码:

  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; }