繁体   English   中英

Npgsql/Postgresql:“函数不存在”错误消息

[英]Npgsql/ Postgresql: “function does not exist” error message when it does

这让我摸不着头脑。 有一个类似的问题可能与“函数不存在”有关,但我真的认为它确实存在并且PostgreSQL 函数不存在但答案似乎不是很明显。 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 窗口正常执行。

我的连接字符串类似于:

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]

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

注意 postgres 允许函数重载,所以不仅函数 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: 函数不存在

另一个让我很头疼的问题是 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))

这就是为什么对您的数据库/组织中的大小写约定达成一致并坚持使用它很重要(所有小写​​字母都很常见)

另一种选择,尽管也容易脆弱,根本不绑定命名参数,而是使用参数的序数位置来绑定它,例如

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)

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

感谢您的帮助!

我刚刚遇到了同样的问题,这是我的发现

出现这个错误的原因是函数创建后,PostgreSQL 自动将函数名和参数名转换为小写。 Npgsql调用该函数时,函数名不区分大小写,但参数名区分大小写。

我花了半天时间寻找错误来源。 刚刚将 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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM