I'm using Dapper 1.31 from Nuget. I have this very simple code snippet,
string connString = ""; string query = ""; int val = 0; CancellationTokenSource tokenSource = new CancellationTokenSource(); using (IDbConnection conn = new SqlConnection(connString)) { conn.Open(); val = (await conn.QueryAsync<int>(query, tokenSource.Token)).FirstOrDefault(); }
When I press F12 on QueryAsync
, it points me to
public static Task<IEnumerable<T>> QueryAsync<T> ( this IDbConnection cnn, string sql, dynamic param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null );
There is no CancellationToken
on its signature.
Questions:
tokenSource.Cancel()
would really cancel the method because I don't know how to generate a long running sql query. Will the .Cancel()
really cancel the method and throw OperationCancelledException
?Thank you!
Therefore, cancellation tokens cannot be reused after they have been canceled. If you require an object cancellation mechanism, you can base it on the operation cancellation mechanism by calling the CancellationToken.
A CancellationToken enables cooperative cancellation between threads, thread pool work items, or Task objects. You create a cancellation token by instantiating a CancellationTokenSource object, which manages cancellation tokens retrieved from its CancellationTokenSource. Token property.
You can use a CancellationToken to stop a long running operation when the user cancels a request in the web browser. In other words, using a CancellationToken can help you stop long running requests from using resources when the user has stopped or refreshed the web page.
A CancellationTokenSource object, which provides a cancellation token through its Token property and sends a cancellation message by calling its Cancel or CancelAfter method. A CancellationToken object, which indicates whether cancellation is requested.
You are passing the cancellation token as the parameter object; that won't work.
The first async methods in dapper did not expose a cancellation token; when I tried to add them as an optional parameter (as a separate overload, to avoid breaking existing assemblies), things got very confused with "ambiguous method" compilation problems. Consequently, I had to expose this via a separate API; enter CommandDefinition
:
val = (await conn.QueryAsync<int>( new CommandDefinition(query, cancellationToken: tokenSource.Token) ).FirstOrDefault();
This then passes the cancellation-token down the chain to all the expected places; it is the job of the ADO.NET provider to actually use it, but; it seems to work in most cases. Note that it can result in a SqlException
rather than an OperationCancelledException
if the operation is in progress; this again is down to the ADO.NET provider, but makes a lot of sense: you could have interrupted something important; it surfaces as a critical connection issue.
As for the questions:
Why is the snippet completely buildable assuming that there is no compiler error on the whole solution?
Because... it is valid C#, even if it doesn't do what you expect.
Forgive me as I cannot test if calling tokenSource.Cancel() would really cancel the method because I don't know how to generate long running sql query. Will the .Cancel() really cancels the method and throws OperationCancelledException?
ADO.NET provider-specific, but yes it usually works. As an example of "how to generate long running sql query"; the waitfor delay
command on SQL server is somewhat useful here, and is what I use in the integration tests.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With