使用 Dapper 和 Npgsql 7.0+ 调用 Posgresql 函数

问题描述 投票:0回答:0

如何在 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

非常感谢任何帮助!

c# postgresql dapper npgsql
© www.soinside.com 2019 - 2024. All rights reserved.