在Dapper documentation中,它表示您可以使用IEnumerable
参数多次执行命令。它给出了以下示例:
connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
).IsEqualTo(3); // 3 rows inserted: "1,1", "2,2" and "3,3"
这是否会导致多次往返数据库(即T
中的每个IEnumerable<T>
一次)?或者Dapper是否足够聪明,可以将多个查询转换为批处理并只进行一次往返?文档说一个示例用法是批量加载,所以我怀疑它只进行一次往返,但我想确定它之前我用它来处理对性能敏感的代码。
作为一个后续问题,根据第一个问题的答案,我很好奇如何处理交易?也就是说,整个T
集合中是否有一个事务,或者每个T
有一个事务?
答案 0 :(得分:0)
我终于再次看到了这个。查看源代码(在\Dapper\SqlMapper.cs
中),我在方法ExecuteImpl
中找到了以下代码段:
// ...
foreach (var obj in multiExec)
{
if (isFirst)
{
masterSql = cmd.CommandText;
isFirst = false;
identity = new Identity(command.CommandText, cmd.CommandType, cnn, null, obj.GetType(), null);
info = GetCacheInfo(identity, obj, command.AddToCache);
}
else
{
cmd.CommandText = masterSql; // because we do magic replaces on "in" etc
cmd.Parameters.Clear(); // current code is Add-tastic
}
info.ParamReader(cmd, obj);
total += cmd.ExecuteNonQuery();
}
// ...
有趣的部分是在调用ExecuteNonQuery
的倒数第二行。在for
循环的每次迭代中调用该方法,因此我猜它不是基于集合操作的意义上的批处理。因此,需要多次往返。但是,它的批处理意味着所有操作都在同一个连接上执行,如果指定的话,在同一个事务中执行。
我能想到进行基于集合的操作的唯一方法是为感兴趣的对象创建一个自定义的表值类型(在数据库中)。然后,在.NET代码中传递一个包含匹配名称和类型的DataTable
对象作为命令参数。如果有办法在不必为每个对象创建表值类型的情况下执行此操作,我很乐意听到它。