Npgsql/Postgresql:"function does not exist" 错误消息

Npgsql/ Postgresql: "function does not exist" error message when it does

为此挠头。在 "function does not exist," but I really think it does and PostgreSQL function does not exist 上可能有一个类似的问题,但答案似乎不是很明显。 PostgreSQL 9.5.

我有一个基于 Npgsql 的成员资格查询,如下所示:

using (var conn = new NpgsqlConnection(ConnectionString))
{
    conn.Open();
    using (var comm = new NpgsqlCommand("get_user_by_username", conn))
    {
        comm.CommandType = CommandType.StoredProcedure;
        comm.Parameters.Add("_user_name", NpgsqlDbType.Varchar, 250).Value = username;
        comm.Parameters.Add("_application_name", NpgsqlDbType.Varchar, 250).Value = _ApplicationName;
        comm.Parameters.Add("_online", NpgsqlDbType.Boolean).Value = userIsOnline;
        using (var reader = comm.ExecuteReader())
        {
            return GetUsersFromReader(reader).OfType<MembershipUser>().FirstOrDefault();
        }
    }
}

这个函数存在于我的 postgresql 数据库中:

CREATE OR REPLACE FUNCTION public.get_user_by_username(
    _user_name character varying,
    _application_name character varying,
    _online boolean)
  RETURNS SETOF user_record AS
$BODY$begin

if _online then
    return query
    update users
    set
        last_activity = current_timestamp
    where
        lower(application_name) = lower(_application_name)
        and lower(user_name) = lower(_user_name)
    returning
        user_id,
        user_name,
        last_activity,
        created,
        email,
        approved,
        last_lockout,
        last_login,
        last_password_changed,
        password_question,
        comment;
else
    return query
    select
        user_id,
        user_name,
        last_activity,
        created,
        email,
        approved,
        last_lockout,
        last_login,
        last_password_changed,
        password_question,
        comment
    from
        users
    where
        lower(application_name) = lower(_application_name)
        and lower(user_name) = lower(_user_name);
        end if;

end;

$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
  ROWS 1000;
ALTER FUNCTION public.get_user_by_username(character varying, character varying, boolean)
  OWNER TO (configured db login);

我已经对连接字符串进行了检查、双重检查和三次检查……它指向这个数据库,并且具有正确的登录名。该函数在 pgAdmin window.

中执行良好

我的连接字符串类似于:

Server=localhost;Port=5432;Database=mysecuritydb;User Id=(configured db login);Password=(my password);Pooling=true;ConvertInfinityDateTime=true;

...使用这些凭据,我可以看到函数:

然而,当我在我的 asp.net 项目中将其用作引用库时,我收到以下消息:

Server Error in '/' Application.

42883: function get_user_by_username(_user_name => character varying, _application_name => character varying, online => boolean) does not exist

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: Npgsql.PostgresException: 42883: function get_user_by_username(_user_name => character varying, _application_name => character varying, online => boolean) does not exist

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 


[PostgresException (0x80004005): 42883: function get_user_by_username(_user_name => character varying, _application_name => character varying, online => boolean) does not exist]

我使用这个库有一段时间了,但这是我第一次看到这个消息。有什么我想念的吗?

所以@JGH 发现错误消息中的签名变量名称在库中与发布的代码中略有不同......这不应该发生,但我下载了源代码,编译它作为一个依赖项目,一切正常。所以,预编译库有问题,我可以解决。

感谢您的帮助!

注意 postgres 允许 function overloading,因此不仅函数 NAME 需要存在,而且函数参数的类型也将用于确定使用哪个重载,例如

CREATE OR REPLACE FUNCTION public.get_user_by_username(varchar, varchar, boolean)   

的功能不同
CREATE OR REPLACE FUNCTION public.get_user_by_username(varchar, boolean, varchar)

调用这些函数时,参数名称、类型和可能的顺序必须全部匹配,否则你会得到

Npgsql.PostgresException: 42883: function does not exist

另一个一直困扰我的陷阱是 Postgressql 在定义函数时区分大小写的规则。例如,没有任何周围的 "" 引号,下面的函数定义(使用 pgAdmin 3 中的默认设置):

CREATE FUNCTION MySchema.MyFunction(Parameter1 VARCHAR(40), parameTer2 VARCHAR(20))

使用签名注册函数:(使用 IDE 工具验证)

myschema.myfunction(parameter1 VARCHAR(40), parameter2 VARCHAR(20))

因此,在 C# 中尝试绑定到

command.Parameters.Add("Parameter1", NpgsqlDbType.Varchar, 40);
command.Parameters.Add("parameTer2", NpgsqlDbType.Varchar, 20);

将因错误而失败。相反,您需要绑定全小写参数,即

command.Parameters.Add("parameter1", NpgsqlDbType.Varchar, 40);
command.Parameters.Add("parameter2", NpgsqlDbType.Varchar, 20);

除非您用引号定义函数:

CREATE FUNCTION "MySchema"."MyFunction"("Parameter1" VARCHAR(40), "parameTer2" VARCHAR(20))

这就是为什么在您的数据库/组织中就大小写约定达成一致并坚持使用它很重要(all lowercase 很常见)

另一种方法虽然也很脆弱,但根本不绑定命名参数,而是使用参数的序号位置来绑定它,例如

var myParameter = new NpgsqlParameter
{
    // Leave `ParameterName` out entirely,
    Direction = ParameterDirection.Input,
    IsNullable = false,
    NpgsqlDbType = NpgsqlDbType.Varchar,
    Size = 20,
    Value = "SomeValue"
};
command.Parameters.Add(myParameter);
// Same for other parameter(s)

我刚遇到同样的问题,这里是 my finding:

The reason for this error is that after the function is created, PostgreSQL automatically converts the function name and parameter name to lowercase. When Npgsql calls this function, the function name is not case sensitive, but the parameter name is case sensitive.

我花了半天时间寻找错误来源。刚刚将 Npgsql 从 2.2.5 升级到 4.1.5,将 PostgreSQL 从 9 升级到 13,我的代码停止使用 42883: function does not exist

我已将 C# 代码中的所有参数都设为小写

var data = dataConnection.QueryProc<FormOutput>("get_form_data", new[] {
    new DataParameter("countryid", countryId),
    new DataParameter("keyvalue", key),
    new DataParameter("maxqty", maxFormQty) });

处理这个错误

函数声明如下

create or replace FUNCTION get_form_data (countryId varchar, key varchar, maxQty int)