如何在 C# 中使用 dapper 调用带参数的 postgresql 函数?我可以很好地调用存储过程,但是函数会抛出异常。
我有一个简单的用户数据库表:
Create TABLE usrs.user(id uuid PRIMARY KEY, name varchar(50))
一个简单的存储过程:
CREATE OR REPLACE PROCEDURE usrs.upsert_user(IN new_id uuid, IN new_name character varying)
LANGUAGE plpgsql
AS $procedure$
BEGIN
INSERT into usrs.user(id, name)
Values(new_id, new_name)
ON CONFLICT(id)
DO
UPDATE SET
name = new_name;
END;
$procedure$;
还有一个简单的功能:
CREATE OR REPLACE FUNCTION usrs.get_user(user_id uuid)
RETURNS TABLE(id uuid, name character varying)
LANGUAGE plpgsql
AS $function$
BEGIN
RETURN QUERY
SELECT u.id, u.name FROM usrs."user" u
WHERE u.id = user_id;
END
$function$
;
在 C# 中,我有另一个简单的数据访问类:
internal class PostgesDataAccess
{
private readonly IConfiguration _configuration;
public PostgesDataAccess(IConfiguration configuration)
{
_configuration = configuration;
}
public List<T> LoadData<T, U>(string storedProcedure, U parameters, string connectionStringName)
{
string connectionString = _configuration.GetConnectionString(connectionStringName) ?? throw new Exception("No Connection String");
using (IDbConnection connection = new NpgsqlConnection(connectionString))
{
List<T> rows = connection.Query<T>(storedProcedure, parameters, commandType: CommandType.StoredProcedure).ToList();
return rows;
}
}
public void SaveData<T>(string storedProcedure, T parameters, string connectionStringName)
{
string connectionString = _configuration.GetConnectionString(connectionStringName) ?? throw new Exception("No Connection String");
using (IDbConnection connection = new NpgsqlConnection(connectionString))
{
connection.Execute(storedProcedure, parameters, commandType: CommandType.StoredProcedure);
}
}
}
我可以这样调用存储过程:
public void UpsertUser(Guid id, string name)
{
var dataAccess = new PostgesDataAccess(_configuration);
var parameters = new { @new_id = id, @new_name = name };
dataAccess.SaveData<dynamic>("usrs.upsert_user", parameters, "Default");
}
这很好用,没有问题。
但这不起作用:
public UserModel GetUser(Guid id)
{
var dataAccess = new PostgesDataAccess(_configuration);
var parameters = new { @user_id = id };
return dataAccess.LoadData<UserModel, dynamic>("usrs.get_user", parameters, "Default").Single();
}
我收到一条错误消息“Npgsql.PostgresException: '42883: procedure usrs.get_user(user_id => uuid) does not exist”
我可以修改 DataAccess.LoadData 以使用
commandType: CommandType.Text
并像这样调用 LoadData 函数:
public UserModel GetUser(Guid id)
{
var dataAccess = new PostgesDataAccess(_configuration);
var parameters = new { };
return dataAccess.LoadData<UserModel, dynamic>($"select * from usrs.get_user('{id}')",parameters, "Default").Single();
}
但这似乎不对。我知道我可以在 SqlServer 中使用相同的 C# 代码而不会出现任何问题,因此它必须与存储过程和函数有关。在 Npgsql 7 中,他们更改了 commandType 参数以调用存储过程,我觉得没有办法调用函数? :https://www.npgsql.org/doc/basic-usage.html#stored-functions-and-procedures
非常感谢任何帮助!