Skip to content

Dapper cancelling only ExecuteReaderAsync not Reader.ReadAsync with MultiMap #555

Open
@SelvinPL

Description

@SelvinPL

Dapper will fail with such Test

        async Task<IEnumerable<Product>> Test()
        {
            CancellationTokenSource cancel = new CancellationTokenSource();
                try
                {
                    const string sql = @"select 1 as id, 'abc' as name, 2 as id, 'def' as name
union all select 1 as id, 'abc' as name, 2 as id, 'def' as name";
                    var productQuery = await connection.QueryAsync<Product, Category, Product>(new CommandDefinition(sql, cancellationToken: cancel.Token), (p, c) => {
                        p.Category = c;
                        //we cancel it in the middle of reading
                        cancel.Cancel();
                        return p;
                    }).ConfigureAwait(false);
                    return productQuery;
                }
                catch (Exception agg)
                {
                    //should be SqlException with message canceled
                }
            return null;
        }

        public async Task TestCancelInReaderReadAsync()
        {
            var res = await Test();
            res.IsEqualTo(null);
        }

solution:
replace all code like(in SQlMapper.Async.cs):

using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
{
/*...*/
}

with

using (var cmd = (DbCommand)command.SetupCommand(cnn, info.ParamReader))
{
     using (var reg = command.CancellationToken.Register(() => cmd.Cancel()))
     {
/*...*/
     }
}

solution is simillar to this answer on SO but he is doing it at wrong place (and not dissposing the registration) ...

Metadata

Metadata

Assignees

No one assigned

    Labels

    v3.0Changes awaiting the next breaking release

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions