使用 Dapper (C#) 调用 PostgreSQL 存储过程

Posted

技术标签:

【中文标题】使用 Dapper (C#) 调用 PostgreSQL 存储过程【英文标题】:Using Dapper (C#) to call PostgreSQL stored procedure 【发布时间】:2020-12-07 16:59:10 【问题描述】:

我发布这个有两个原因

    我是 PostgreSQL 新手,将这些信息拼凑起来需要一段时间,所以我认为其他人会觉得这很有帮助,并且 询问是否有另一种方法来调用 PostgreSQL 存储过程,不需要将所有参数都包含在存储过程名称/签名中。

下面使用 Dapper 和 Npgsql 调用一个 PostgreSQL 存储过程,插入(传入的空 id_inout)或更新记录(id_inout 有一个值)。

我想了解为什么 PostgreSQL 在进行调用时需要整个存储过程签名。

    public static int? PO_Save(PurchaseOrder po)
    

        int? recordId = null;           

        using (var cn = new NpgsqlConnection(AppSettings.ConnectionString))
        
            if (cn.State != ConnectionState.Open)
                cn.Open();

            var procName = "CALL po_save(@in_ponumber,@in_deliverydate,@in_bldnum," +
                "@in_facname,@in_facnumber,@in_facaddress1,@in_facaddress2,@in_city," +
                "@in_state,@in_zip,@in_theme,@id_inout)";
            var p = new Dapper.DynamicParameters();
            p.Add("@in_ponumber", po.PONumber);
            p.Add("@in_deliverydate", po.DeliveryDate);
            p.Add("@in_bldnum", po.BldNum);
            p.Add("@in_facname", po.FacName);
            p.Add("@in_facnumber", po.FacNumber);
            p.Add("@in_facaddress1", po.FacAddress1);
            p.Add("@in_facaddress2", po.FacAddress2);
            p.Add("@in_city", po.City);
            p.Add("@in_state", po.State);
            p.Add("@in_zip", po.Zip);
            p.Add("@in_theme", po.Theme);
            p.Add("@id_out", po.POID, null, ParameterDirection.InputOutput);
            var res = cn.Execute(procName, p);
            recordId = p.Get<int>("@id_inout");
        

        return recordId;
    

【问题讨论】:

【参考方案1】:

您应该能够将commandType: CommandType.StoredProcedure 传递给Execute,例如:

var res = cn.Execute(
    "po_save",
    new 
        in_ponumber = po.PONumber,
        in_deliverydate = po.DeliveryDate,
        // etc...
    ,
    commandType: CommandType.StoredProcedure,
);

这是带有此类示例的文档:https://github.com/StackExchange/Dapper/blob/main/Readme.md#stored-procedures

【讨论】:

不幸的是,对于 PostgreSQL,CommandType.StoredProcedure 是为函数保留的 “请注意,CommandType.StoredProcedure 将生成一个 SELECT 命令 - 适用于函数 - 而不是适用于过程的 CALL 命令。 [...] 调用存储过程的唯一方法是编写自己的 CALL my_proc(...) 命令,无需设置 CommandBehavior.StoredProcedure。” (npgsql.org/doc/basic-usage.html#stored-functions-and-procedures)。尝试设置 CommandType 会导致以下异常 - Npgsql.PostgresException: 42809: proc-name () ... is an procedure.

以上是关于使用 Dapper (C#) 调用 PostgreSQL 存储过程的主要内容,如果未能解决你的问题,请参考以下文章

C# Dapper基本三层架构使用 (Web UI层)

Dapper use Table Value Parameter in C# (Sql Server 数组参数)

使用没有字母参数的 Postgresql 的 Dapper 存储过程

如何使用 Dapper.NET 将 C# 列表插入数据库

选择语句:列名无效,在 C# 中使用 Dapper

C#的dapper使用