【问题标题】:Dapper and execution of multiple same commands?小巧玲珑并执行多个相同的命令?
【发布时间】:2019-11-10 23:28:12
【问题描述】:

dapper 如何多次执行同一个命令?正如我在下面写的插入 sql,并使用列表参数调用 Dapper 的执行方法,所以我将插入 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)
}

version1和version2到底是一样的还是不一样?

【问题讨论】:

标签: c# .net ado.net dapper


【解决方案1】:

当您将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 有,请使用它。

回答您的评论:

如果我创建事务,并在其中调用多个插入,该事务是否会进行 1 次往返数据库以调用所有这些?还是inserts还是会一一执行?

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

【讨论】:

  • @AmitJoshi,所以当我在事务中调用 foreach 并进行 1000 次插入时,如果在 500 次插入后有人从该表中调用 select,那么 805 插入将被破坏并且事务将回滚,一个在插入过程中选择行的人会有回滚的行吗?
  • @CSharpBeginner:它还取决于SqlTransaction.IsolationLevel。但这件事超出了 Dapper 的范围。这就是 ADO.NET 或 RDBMS 的工作方式。 Dapper 与它无关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 2011-10-15
  • 2012-04-08
  • 1970-01-01
  • 2022-08-18
  • 1970-01-01
相关资源
最近更新 更多