2017-03-03 57 views
0

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" 

这是否会导致多次往返于数据库(一个在IEnumerable<T>每个T即)?还是Dapper足够聪明,可以将多个查询转换为批处理,并且只需执行一次往返?该文档说明了一个示例用法是批量加载,所以我怀疑它只做了一次往返,但我想确保在将它用于性能敏感的代码之前。

作为后续问题,根据第一个问题的答案,我会好奇如何处理交易?也就是说,整套T s是否有一笔交易,或者每笔交易T有一笔交易?

+0

为什么不测试它并运行SQL Profiler? –

回答

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。如果有办法做到这一点,而不必为每个对象创建一个表值类型,我很乐意听到它。