dapper如何多次执行同一命令?正如我在下面编写的那样,插入sql,并使用list参数调用Dapper的execute方法,因此我将插入3个对象。
问题:dapper是否进行3次往返Sql Server的执行以执行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)
}
版本1和版本2是否全部相同?
答案 0 :(得分:2)
当您将IEnumerable
传递到Execute
以插入多个项目时,每个项目都会被独立插入。就是说,您介绍的两种情况没有太大的区别。
Dapper通过接受IEnumerable
来简化多个项目的插入。它没有在内部实现批量插入之类的功能。
看看this文章:
但是这种方法将每个命令作为一个独立的事务发送,这可能会导致在执行一个或多个语句时出错的情况下产生不一致。解决方法是使用IDBTransaction对象创建一个涵盖所有执行的显式事务。性能和可伸缩性要比仅执行一个传递一组对象的命令要差(由于网络延迟和较长的事务处理),但至少可以保证一致性。
但是,由于Dapper支持SQL Server的Table-Valued-Parameters和JSON,因此我建议您在需要将值数组传递给参数的情况下使用其中之一。我将在以后的文章中讨论它们,敬请期待。
现在,如果必须传递一个包含10.000个或更多值的数组怎么办?在这里,正确的选择是使用大容量负载,更具体地说,对于SQL Server,使用BULK INSERT命令,但不幸的是,Dapper本身不支持该命令。解决方法是仅在此处使用常规的SqlBulkCopy类,即可完成。
或者,您可以考虑使用Dapper Plus - Bulk Insert之类的工具。
您可能会了解有关批量插入的更多信息以及实现此here的技巧。此外,Dapper supports TVPs。如果您使用RDBMS,请使用它。
回答您的评论:
如果我创建事务并在其中调用多个插入,那么事务是否进行一次往返数据库的调用以调用所有事务?还是插入仍将一一执行?
事务与批量插入无关。如果在事务中包装代码块(有问题的任何版本),结果将不会改变。整个事务将提交或回滚。如果没有事务,则如果某处之间的操作失败,则可能会遇到一致性问题。通过将代码包装在事务中,您可以避免此问题。您的核心问题-批量插入保持原样。