如何使用 Dapper 将 list<myobject> 作为参数插入到存储过程

Posted

技术标签:

【中文标题】如何使用 Dapper 将 list<myobject> 作为参数插入到存储过程【英文标题】:How do I use Dapper to insert a list<myobject> as parameter to a stored procedure 【发布时间】:2021-12-25 21:27:50 【问题描述】:

我有一个包含 10 列的 SQL Server 表:

CREATE TABLE [bank].[CommonPostingsFromBankFiles]
(
    [Id] [INT] IDENTITY(1,1) NOT NULL,
    [BankRegistrationNumber] [INT] NOT NULL,
    [BankAccountNumber] [BIGINT] NOT NULL,
    [BankName] [NVARCHAR](50) NULL,
    [BankAccount] [NVARCHAR](50) NULL,
    [PostingAmount] [DECIMAL](18, 2) NOT NULL,
    [PostingDate] [DATE] NOT NULL,
    [Primo] [CHAR](1) NULL,
    [PostingText] [NVARCHAR](100) NULL,
    [HideThisRecord] [BIT] NULL,

    CONSTRAINT [PK_CommonPostingsFromBankFiles] 
        PRIMARY KEY CLUSTERED ([BankRegistrationNumber] ASC,
                               [BankAccountNumber] ASC,
                               [PostingAmount] ASC,
                               [PostingDate] ASC)
                WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                      IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                      ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) 

还有一个需要 7 个参数的存储过程:

ALTER PROCEDURE [bank].[spInsertCommonPostings]
    (@BankRegistrationNumber INT,
     @BankAccountNumber BIGINT,
     @BankName NVARCHAR(50),
     @PostingAmount DECIMAL(18, 2),
     @PostingDate DATE,
     @Primo CHAR(1),
     @PostingText NVARCHAR(100))
AS
BEGIN
    IF NOT EXISTS (SELECT *
                   FROM bank.CommonPostingsFromBankFiles
                   WHERE BankRegistrationNumber = @BankRegistrationNumber
                     AND BankAccountNumber = @BankAccountNumber
                     AND BankName = @BankName
                     AND PostingAmount = @PostingAmount
                     AND PostingDate = @PostingDate)
        INSERT INTO bank.CommonPostingsFromBankFiles (BankRegistrationNumber, BankAccountNumber,
                                                      BankName, PostingAmount,
                                                      PostingDate, Primo, PostingText)
        VALUES (@BankRegistrationNumber, @BankAccountNumber,  
                @BankName, @PostingAmount, 
                @PostingDate, @Primo, @PostingText);
END;

我想要的是使用 Dapper 使用存储过程将List&lt;Postings&gt; 写入表。

我已经搜索和搜索,但没有找到对我有帮助的示例。

如果我这样做

connection.Execute(sql: "spMyStoredProc", MyList, commandType: CommandType.StoredProcedure);

我收到一个错误

过程或函数 spMyStoredProc 指定的参数过多

如果我用存储过程中的 sql 替换存储过程的名称并将 CommandType 设置为 Text,它会按预期工作。

谁能给我发一个例子,展示如何使用我的存储过程插入我的列表。

谢谢, 史蒂芬

【问题讨论】:

如果要将对象列表传递给过程,则需要接受表值参数。您将需要定义一个类似于您的CREATE TABLECREATE TYPE...AS TABLE... 并指示Dapper 识别它。此处举例说明:dapper-tutorial.net/parameter-table-valued-parameter 当您使用命令文本时,Dapper 可以从 SQL 中检查需要哪些属性。当您调用 SP 时,它不能 - 它必须假设声明的所有内容都是想要的 - 在这种情况下,假设是不正确的。或者基本上:“@Caius 说了什么” 【参考方案1】:

简单地说,假设您的 c# 对象中的属性名称与存储过程中的参数名称相同,您可以:

MyList.ForEach(x => connection.Execute(sql: "spMyStoredProc", x, commandType: CommandType.StoredProcedure));

如果参数/道具未对齐,则提供一个匿名类型可能是最简单的,该类型填充了来自 x 的值来覆盖它们

MyList.ForEach(x => connection.Execute(
  sql: "spMyStoredProc",
  new  BankRegistrationNumber = x.BankRN, ... , 
  commandType: CommandType.StoredProcedure
));

对于 10 个对象的列表,它将调用 proc 10 次;这不是最快的方法,但我认为您没有说明任何特定的目标和性能等。

【讨论】:

非常感谢!你的建议解决了我的问题。我的收藏包含大约 1.000 个元素,但我在上面花费 4 秒钟没有问题。

以上是关于如何使用 Dapper 将 list<myobject> 作为参数插入到存储过程的主要内容,如果未能解决你的问题,请参考以下文章

使用Dapper时,如何将MySqlParameters[] 变成Dapper.DynamicParameters动态对象

使用 dapper c# 填充列表对象

Dapper基本增删改查

Dapper 条件语句(Where) 中参数使用

使用Dapper.NET异步API时如何尊重CommandTimeout

Android ViewModel 附加参数