如何在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; }