Looks like Dapper twice enumerates IEnumerable passed as TVP
var numbers = GenerateNumbers(3);
BulkInsert(numbers);
static IEnumerable<int> GenerateNumbers(int count)
{
for (int i = 0; i < count; i++)
{
Console.WriteLine(i);
yield return i;
}
}
void BulkInsert(IEnumerable<int> numbers)
{
var records = numbers.Select(x => MapToSqlDataRecord(x));
var sql = @"INSERT INTO [Test] (Id) SELECT Id FROM @tvp;";
using (var connection = new SqlConnection(connectionString))
{
connection.Execute(sql, new { tvp = records.AsTableValuedParameter("dbo.TestType") });
}
}
static SqlDataRecord MapToSqlDataRecord(int i)
{
var record = new SqlDataRecord(
new SqlMetaData("Id", SqlDbType.Int)
);
record.SetInt32(0, i);
return record;
}
this code writes to console
0
0
1
2
and if I pass enumerable from database it throws exception because can not open second reader on same connection (same enumerable works fine using ADO.Net)

I believe this is the first enumeration
Looks like Dapper twice enumerates IEnumerable passed as TVP
this code writes to console
0
0
1
2
and if I pass enumerable from database it throws exception because can not open second reader on same connection (same enumerable works fine using ADO.Net)
I believe this is the first enumeration