C# 如何使用Npgsql和PostgreSQL实现ExecuteScalar函数?

C# 如何使用Npgsql和PostgreSQL实现ExecuteScalar函数?,c#,postgresql,ado.net,npgsql,C#,Postgresql,Ado.net,Npgsql,我正在学习Npgsql和PostgrSQL。我无法让这个简单的测试工作。以下是我的功能: CREATE OR REPLACE FUNCTION count_customers(_customerid integer DEFAULT NULL::integer) RETURNS void AS $BODY$ BEGIN SELECT COUNT(*) FROM Customers WHERE CustomerId = _customerid or _customerid is null; E

我正在学习Npgsql和PostgrSQL。我无法让这个简单的测试工作。以下是我的功能:

CREATE OR REPLACE FUNCTION count_customers(_customerid integer DEFAULT NULL::integer)
  RETURNS void AS
$BODY$
BEGIN
SELECT COUNT(*) FROM Customers 
WHERE CustomerId = _customerid or _customerid is null;
END
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
这是我的C代码:

[Test]
public void ExecuteScalarTest()
{
    NpgsqlConnection conn = new NpgsqlConnection("Host=localhost; Database=postgres; User ID=postgres; Password=password");
    conn.Open();
    IDbCommand command = conn.CreateCommand();
    command.CommandText = "count_customers";
    command.CommandType = CommandType.StoredProcedure;
    object result = command.ExecuteScalar();
    conn.Close();
    Console.WriteLine(result);
}
我一直得到下面的错误。
Npgsql.NpgsqlException:错误:42601:查询没有结果数据的目标

这与Npgsql无关。问题出在存储函数中

您已经用PL/PgSQL编写了一个简单的包装器,但还没有使用RETURN。在PL/PgSQL中不能使用SELECT,除非其输出通过SELECT INTO或作为子查询(如x:=SELECT…)传递给变量。。。或返回查询语句

你应该写:

BEGIN
  RETURN QUERY 
    SELECT COUNT(*) FROM Customers 
    WHERE CustomerId = _customerid
       OR _customerid is null;
END
并将您的过程定义为RETURNS bigint,因为如果函数返回void,显然无法从函数中获取值。此外,该功能稳定,不易失。如果你不确定,什么也别说。成本也是如此——除非你有充分的理由,否则不要考虑

但这仍然过于复杂。对于这样的调用,您可以使用一个简单的sql函数,例如

CREATE OR REPLACE FUNCTION count_customers(_customerid integer DEFAULT NULL::integer)
RETURNS bigint LANGUAGE sql STABLE AS
$BODY$
SELECT COUNT(*) FROM Customers 
WHERE CustomerId = $1 OR $1 is null;
$BODY$;

+1感谢您显示您的代码和确切的错误消息文本。将来,PostgreSQL版本也总是首选。