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.
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.