Search code examples
c#dapperiasyncenumerable

Rewriting the GetAsync method using IAsyncEnumerable in Dapper


I just learned about QueryUnbufferedAsync and IAsyncEnumerable in here https://www.learndapper.com/dapper-query/selecting-unbuffered-async and wanted to use it in my own data service class but I am doing something wrong as this is not compiling. I think I am messing up the return data types but I couldn't figure out the way to use it.

Here is my code:

private async Task<T> GetAsync2<T>(Func<DbConnection, Task<T>> operation)
{
    if (operation is null) { throw new ArgumentNullException(nameof(operation)); }

    await using DbConnection myCon = new SnowflakeDbConnection("myConnectionString");
    await myCon.OpenAsync();

    var result = await databaseOperation(myCon);

    return result;
}

public async Task<IAsyncEnumerable<T>> GetAllAsync<T>(string sqlSelect) => await GetAsync2(conn => conn.QueryUnbufferedAsync<T>(sqlSelect));

This is the build error I get:

The type arguments for method 'GetAsync2(Func<DbConnection, Task>)' cannot be inferred from the usage.


Solution

  • QueryUnbufferedAsync returns an IAsyncEnumerable. It's not async Task<IAsyncEnumerable because IAsyncEnumerable is already async-friendly.

    So you need another overload that accepts a non-Task delegate.

    However, because of the fact it's unbuffered, you can't close the connection until the data is read. Therefore you need (and should anyway) rely on Dapper to open and close the connection once the data is fully read. Dapper can handle this as long as the connection was closed when you started the operation.

    private T GetFromDb<T>(Func<DbConnection, T> operation)
    {
        // do NOT add using
        var myCon = new SnowflakeDbConnection("myConnectionString");
        var result = operation(myCon);
        return result;
    }
    
    public IAsyncEnumerable<T> GetAllAsync<T>(string sqlSelect) =>
        GetFromDb(conn => conn.QueryUnbufferedAsync<T>(sqlSelect));
    

    However at this point I'm not sure what you gain by messing with delegates.