Dapper 和执行多个相同的命令?

Dapper and execution of multiple same commands?

dapper如何多次执行同一条命令?正如我在下面所写的插入 sql,并使用列表参数调用 Dapper 的执行方法,所以我将插入 3 个对象。

问题:dapper 是向 Sql 服务器进行 3 次往返以执行 3 次插入,还是以某种方式将其发送为 1 次往返以调用 3 次插入?

我只是想知道像这样使用它是否比仅 foreach 和调用一个插入一个插入有任何优势,或者它是否完全相同。

Version 1.

var sqlInsert = $"INSERT INTO Book (Id, Title) Values (@Id, @Title)";
var parameters = new List<Book> { new Book("Damian Book", 123), new Book("XXX Book", 156), new Book("Zonk BOok", 167) };

connection.Execute(sqlInsert, parameters);

Version 2.

foreach (var book in parameters)
{
    connection.Execute(sqlInsert, book)
}

version1和version2到底是不是一样?

当您将 IEnumerable 传递给 Execute 以插入多个项目时,每个项目都会独立插入。也就是说,您介绍的两种情况并没有太大区别。

Dapper 只是通过接受 IEnumerable 来方便插入多个项目。它没有在内部实现类似批量插入的功能。

看看this文章:

But this approach sends every command as a single, stand-alone transaction, which may cause inconsistencies in case of error while executing one or more statements. The workaround here is to use an IDBTransaction object to create an explicit transaction that covers all the executions. Performances and scalability will be worse than executing just one command passing an array of objects (due to network latency and thus longer transactions), but at least consistency will be guaranteed.

But since Dapper supports SQL Server’s Table-Valued-Parameters and also JSON my recommendation is to use one of those if you need to pass an array of values to a parameter. I’ll discuss about them in future articles, so stay tuned.

Now, what about if you have to pass an array of, say, 10.000 values or more? The right choice, here, is to use a bulk load, and more specifically with SQL Server the BULK INSERT command, which is, unfortunately, not supported by Dapper natively. The workaround is to just use the regular SqlBulkCopy class here and you’re done.

或者,您可以考虑使用像 Dapper Plus - Bulk Insert 这样的工具。

您可以阅读更多关于批量插入和实现此目的的 hack here. Also, Dapper supports TVPs。如果您的 RDBMS 有,请使用它。

回答您的评论:

If I create transaction, and invoke multiples inserts within it, does the transaction make 1 roundtrip to database to invoke all of them? Or inserts will be still executed one by one ?

事务与批量插入无关。如果你在交易中包装你的代码块(你提到的任何版本),结果不会改变......除了一个。整个事务将提交或回滚。如果没有事务,如果某处操作失败 in-between,您可能会遇到一致性问题。通过将代码包装在事务中,您可以简单地避免这个问题。您的核心问题 - 批量插入保持原样。