DapperLib / DapperLib/Dapper

Multiple enumerations of IEnumerable<SqlDataRecord> passed as TVP

Open
#2,064 7 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug up-for-grabs
Dominant language
C#
Stars
18.4k
Forks
3.7k
Avg merge
5h 8m
Merged PRs (30d)
1

Description

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)

image
I believe this is the first enumeration

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the AsTableValuedParameter and Execute path shown in the issue, then reproduce the sample with GenerateNumbers and SqlDataRecord. Trace where the TVP records are enumerated and verify the database-backed enumerable case; done means the records are consumed once without opening a second reader.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, sql
Domain
database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.