Jer*_*acs 4 c# sql postgresql npgsql
这让我摸不着头脑。有一个类似的问题可能与“函数不存在”有关,但我真的认为它确实存在并且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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这个函数存在于我的 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);
Run Code Online (Sandbox Code Playgroud)
我已经检查、双重检查和三重检查连接字符串......它指向这个数据库,并具有正确的登录名。该函数可以从 pgAdmin 窗口正常执行。
我的连接字符串类似于:
Server=localhost;Port=5432;Database=mysecuritydb;User Id=(configured db login);Password=(my password);Pooling=true;ConvertInfinityDateTime=true;
Run Code Online (Sandbox Code Playgroud)
然而,当我在 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]
Run Code Online (Sandbox Code Playgroud)
我已经使用这个库一段时间了,但这是我第一次看到这条消息。有什么我想念的吗?
注意 postgres 允许函数重载,所以不仅函数 NAME 需要存在,而且函数参数的类型也将用于确定使用哪个重载,例如
CREATE OR REPLACE FUNCTION public.get_user_by_username(varchar, varchar, boolean)
Run Code Online (Sandbox Code Playgroud)
不是一样的功能
CREATE OR REPLACE FUNCTION public.get_user_by_username(varchar, boolean, varchar)
Run Code Online (Sandbox Code Playgroud)
等等。
调用这些函数时,参数名称、类型和可能的顺序必须全部匹配,否则你会得到
Npgsql.PostgresException: 42883: 函数不存在
另一个让我很头疼的问题是 Postgressql 在定义函数时的区分大小写规则。例如,没有任何周围的""引号,以下函数定义(使用 pgAdmin 3 中的默认设置):
CREATE FUNCTION MySchema.MyFunction(Parameter1 VARCHAR(40), parameTer2 VARCHAR(20))
Run Code Online (Sandbox Code Playgroud)
使用签名注册函数:(使用IDE工具验证这一点)
myschema.myfunction(parameter1 VARCHAR(40), parameter2 VARCHAR(20))
Run Code Online (Sandbox Code Playgroud)
因此,在 C# 中任何尝试绑定到
command.Parameters.Add("Parameter1", NpgsqlDbType.Varchar, 40);
command.Parameters.Add("parameTer2", NpgsqlDbType.Varchar, 20);
Run Code Online (Sandbox Code Playgroud)
将因错误而失败。相反,您需要绑定全小写参数,即
command.Parameters.Add("parameter1", NpgsqlDbType.Varchar, 40);
command.Parameters.Add("parameter2", NpgsqlDbType.Varchar, 20);
Run Code Online (Sandbox Code Playgroud)
除非你用引号定义函数:
CREATE FUNCTION "MySchema"."MyFunction"("Parameter1" VARCHAR(40), "parameTer2" VARCHAR(20))
Run Code Online (Sandbox Code Playgroud)
这就是为什么对您的数据库/组织中的大小写约定达成一致并坚持使用它很重要(所有小写字母都很常见)
另一种选择,尽管也容易脆弱,根本不绑定命名参数,而是使用参数的序数位置来绑定它,例如
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)
Run Code Online (Sandbox Code Playgroud)
所以@JGH发现错误消息中的签名变量名称在库中与发布的代码中略有不同......这是不应该发生的,但我拉下了源代码,将其编译为依赖项目,一切工作正常。所以,预编译库有问题,我可以解决它。
谢谢您的帮助!
| 归档时间: |
|
| 查看次数: |
5686 次 |
| 最近记录: |