为什么我在 .Net 中通过 npgsql 得到异常 运行 一个函数(存储过程)?
Why am I getting exceptions running a function (stored procedure) through npgsql in .Net?
我有一个 .Net 应用程序,它使用 Npgsql 与 Postgresql 数据库对话。网。
我有一个 postgresql 函数,我试图通过 Npgsql 调用它。
当我直接在 pgadmin 中 运行 时,函数 运行 没问题。
但是,当我从我的 .Net (C#) 应用程序 运行 它时,它抛出异常。
这是函数的 "cleansed" 版本:
CREATE OR REPLACE FUNCTION Function1(id_param integer,
date1_param date,
date2_param date)
RETURNS TABLE (
field1 character varying,
field2 character varying,
field3 bigint)
AS $$
BEGIN
RETURN QUERY
SELECT table1.field1,
table2.field2,
table3.field3
FROM table1
LEFT JOIN table2 on table1.empno = table2.empno
LEFT JOIN public.table3 on table1.docnum = table3.number
WHERE table1.entrydate >= date1_param
AND table2.date1 >= date1_param
AND table2.date2 <= date2_param;
END;
$$ LANGUAGE plpgsql;
这是我在 运行 时得到的异常:
{"42P01: invalid reference to FROM-clause entry for table \"table1\""}
我的函数中的 JOIN 语句有什么问题导致了这个异常?
谢谢,
约翰B
我不能确定哪里出了问题,但我可以告诉您我在 NpgSql 中成功调用函数的秘诀并将其应用到您的示例中。
首先,您的代码,据我所知:
NpgsqlCommand command = null;
DataTable dtResults = new DataTable();
command = new NpgsqlCommand();
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = functionName;
NpgsqlDataAdapter da = new NpgsqlDataAdapter(command);
da.Fill(dtResults);
在 PostgreSQL 中,函数和存储过程之间有一条模糊的界限(在我的最佳评估中)。为了调用函数,最简单的方法是使用 select
,即使它没有 return 任何东西(虽然你的有),然后使用普通的 DbDataReader
或DbDataAdapter
.
此外,您上面的示例保证参数,none 其中出现在 C# 调用中。
最后,存储过程没有显示完全限定的表。是否有可能 运行 作为 psql 中与 .NET 应用程序中不同的用户 ID?无论哪种方式,添加模式名称都没有坏处。
这是我为您的 .NET 代码推荐的内容:
NpgsqlCommand command = new NpgsqlCommand("select * from Function1(:ID, :DATE1, :DATE2)",
connection);
command.Parameters.Add(new NpgsqlParameter("ID", NpgsqlDbType.Integer));
command.Parameters.Add(new NpgsqlParameter("DATE1", NpgsqlDbType.Date));
command.Parameters.Add(new NpgsqlParameter("DATE2", NpgsqlDbType.Date));
command.Parameters[0].Value = id;
command.Parameters[1].Value = dt1;
command.Parameters[2].Value = dt2;
DataTable dtResults = new DataTable();
NpgsqlDataAdapter da = new NpgsqlDataAdapter(command);
da.Fill(dtResults);
同样,即使您不需要它们,我也会在表和函数前面添加架构名称。
我有一个 .Net 应用程序,它使用 Npgsql 与 Postgresql 数据库对话。网。 我有一个 postgresql 函数,我试图通过 Npgsql 调用它。 当我直接在 pgadmin 中 运行 时,函数 运行 没问题。 但是,当我从我的 .Net (C#) 应用程序 运行 它时,它抛出异常。
这是函数的 "cleansed" 版本:
CREATE OR REPLACE FUNCTION Function1(id_param integer,
date1_param date,
date2_param date)
RETURNS TABLE (
field1 character varying,
field2 character varying,
field3 bigint)
AS $$
BEGIN
RETURN QUERY
SELECT table1.field1,
table2.field2,
table3.field3
FROM table1
LEFT JOIN table2 on table1.empno = table2.empno
LEFT JOIN public.table3 on table1.docnum = table3.number
WHERE table1.entrydate >= date1_param
AND table2.date1 >= date1_param
AND table2.date2 <= date2_param;
END;
$$ LANGUAGE plpgsql;
这是我在 运行 时得到的异常:
{"42P01: invalid reference to FROM-clause entry for table \"table1\""}
我的函数中的 JOIN 语句有什么问题导致了这个异常?
谢谢, 约翰B
我不能确定哪里出了问题,但我可以告诉您我在 NpgSql 中成功调用函数的秘诀并将其应用到您的示例中。
首先,您的代码,据我所知:
NpgsqlCommand command = null;
DataTable dtResults = new DataTable();
command = new NpgsqlCommand();
command.Connection = connection;
command.CommandType = CommandType.StoredProcedure;
command.CommandText = functionName;
NpgsqlDataAdapter da = new NpgsqlDataAdapter(command);
da.Fill(dtResults);
在 PostgreSQL 中,函数和存储过程之间有一条模糊的界限(在我的最佳评估中)。为了调用函数,最简单的方法是使用 select
,即使它没有 return 任何东西(虽然你的有),然后使用普通的 DbDataReader
或DbDataAdapter
.
此外,您上面的示例保证参数,none 其中出现在 C# 调用中。
最后,存储过程没有显示完全限定的表。是否有可能 运行 作为 psql 中与 .NET 应用程序中不同的用户 ID?无论哪种方式,添加模式名称都没有坏处。
这是我为您的 .NET 代码推荐的内容:
NpgsqlCommand command = new NpgsqlCommand("select * from Function1(:ID, :DATE1, :DATE2)",
connection);
command.Parameters.Add(new NpgsqlParameter("ID", NpgsqlDbType.Integer));
command.Parameters.Add(new NpgsqlParameter("DATE1", NpgsqlDbType.Date));
command.Parameters.Add(new NpgsqlParameter("DATE2", NpgsqlDbType.Date));
command.Parameters[0].Value = id;
command.Parameters[1].Value = dt1;
command.Parameters[2].Value = dt2;
DataTable dtResults = new DataTable();
NpgsqlDataAdapter da = new NpgsqlDataAdapter(command);
da.Fill(dtResults);
同样,即使您不需要它们,我也会在表和函数前面添加架构名称。