2014-08-28 3 views
10

Я использую Dapper 1.31 от Nuget. У меня есть этот очень простой фрагмент кода,Аннулирование токена на Dapper

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(); 
} 

Когда я нажимаю F12 на QueryAsync, он указывает мне на

public static Task<IEnumerable<T>> QueryAsync<T> 
    (
     this IDbConnection cnn, 
     string sql, 
     dynamic param = null, 
     IDbTransaction transaction = null, 
     int? commandTimeout = null, 
     CommandType? commandType = null 
    ); 

Там нет CancellationToken на его подписи.

Вопросы:

  • Почему не сниппет полностью работоспособна предполагая, что там нет ошибок компилятора в целом решение?
  • Простите меня, поскольку я не могу проверить, действительно ли вызов tokenSource.Cancel() действительно отменит метод, потому что я не знаю, как создать длинный SQL-запрос. Будет ли .Cancel() действительно отменяет метод и выбрасывает OperationCancelledException?

Спасибо!

+0

'динамический param' займет довольно много ничего. То, что вы делаете, похоже на передачу токена отмены в качестве параметра в 'Console.WriteLine (string, params object [])'. Просто потому, что вы можете передать это, это не означает, что функция поддерживает отмену. –

ответ

19

Вы передаете токен отмены в качестве объекта параметра; это не сработает.

Первые асинхронные методы в dapper не отображали токен отмены; когда я попытался добавить их в качестве необязательного параметра (в качестве отдельной перегрузки, чтобы избежать нарушения существующих сборок), things got very confused with "ambiguous method" compilation problems. Следовательно, мне пришлось разоблачить это через отдельный API; введите CommandDefinition:

val = (await conn.QueryAsync<int>(
    new CommandDefinition(query, cancellationToken: tokenSource.Token) 
).FirstOrDefault(); 

Это затем проходит аннулирование-маркер вниз по цепочке на все ожидаемые места; это работа провайдера ADO.NET на самом деле использовать это, но; он работает в большинстве случаев. Обратите внимание, что при выполнении операции может возникнуть SqlException, а не OperationCancelledException; это снова относится к провайдеру ADO.NET, но имеет большой смысл: вы могли бы прервать что-то важное; он возникает как критическая проблема подключения.

Что касается вопросов:

Почему сниппет полностью работоспособна при условии, что нет ошибок компилятора в целом решение?

Потому что ... это действительно C#, даже если он не делает то, что вы ожидаете.

Простите меня, поскольку я не могу проверить, вызывает ли вызов tokenSource.Cancel() действительно отменяет метод, потому что я не знаю, как генерировать длинный SQL-запрос. Будет ли .Cancel() действительно отменяет метод и выбрасывает OperationCancelledException?

ADO.NET провайдер-специфический, но да, он обычно работает. В качестве примера «как создать длинный SQL-запрос»; команда waitfor delay на сервере SQL здесь несколько полезна, и это то, что я использую в тестах интеграции.

+1

Это отличный ответ от самого автора. Спасибо Marc за альтернативный API! Ну, я в порядке с улавливанием 'SqlException', а не' OperationCancelledException', я опишу здесь логику. Еще раз спасибо! – Pedigree

+1

@Pedigree I * think * Я также выяснил, как заставить его работать правильно в основном API. –

+0

У меня есть еще один вопрос marc, и я не знаю, все ли это в области видимости, почему вы установили '.ConfigureAwait (false)' on * line 78 * of [file: SqlMapperAsync.cs] (https: // github.com/StackExchange/dapper-dot-net/blob/master/Dapper%20NET45/SqlMapperAsync.cs)? Что это на самом деле значит? Благодарю. – Pedigree

1

Вы можете исправить SqlMapper.cs в Dapper lib, добавив следующие строки:

internal IDbCommand SetupCommand(IDbConnection cnn, Action<IDbCommand, object> paramReader) 
    { 
     var cmd = cnn.CreateCommand(); 

#if ASYNC 
     // We will cancel our IDbCommand 
     CancellationToken.Register(() => cmd.Cancel()); 
#endif 

Перестроить свой собственный Dapper LIB и наслаждайтесь :)

Смежные вопросы