2014-08-28 9 views
10

Ich benutze Dapper 1.31 von Nuget. Ich habe diesen sehr einfachen Code-Schnipsel,Widerrufsmarke auf 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(); 
} 

Wenn ich F12 auf QueryAsync drücken, er zeigt mir

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

Es gibt keine CancellationToken auf seiner Unterschrift.

Fragen:

  • das Snippet vollständig bebaubare vorausgesetzt Warum ist, dass keine Compiler-Fehler auf der gesamten Lösung ist?
  • Verzeihen Sie mir, wie ich nicht testen kann, wenn Aufruf tokenSource.Cancel() würde wirklich die Methode abbrechen, weil ich nicht weiß, wie lange SQL-Abfrage zu generieren. Wird die .Cancel() die Methode wirklich abbrechen und OperationCancelledException auslöst?

Vielen Dank!

+0

'dynamische param' nimmt so ziemlich alles genießen. Was Sie tun, ist so etwas wie die Übergabe eines Abbruch-Tokens als Parameter an 'Console.WriteLine (string, params object [])'. Nur weil Sie es weitergeben können, bedeutet dies nicht, dass die Funktion die Löschung unterstützt. –

Antwort

19

Sie übergeben das Abbruch-Token als Parameterobjekt; das wird nicht funktionieren.

Die ersten async-Methoden in dapper haben kein Löschungs-Token verfügbar gemacht; Als ich versuchte, sie als optionalen Parameter hinzuzufügen (als separate Überladung, um das Aufbrechen vorhandener Baugruppen zu vermeiden), things got very confused with "ambiguous method" compilation problems. Folglich musste ich dies über eine separate API offen legen; Geben Sie CommandDefinition:

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

Dies ist dann die Annullierung-Token nach unten durchläuft die Kette zu allen erwarteten Orten; es ist die Aufgabe des ADO.NET-Providers, tatsächlich es verwenden, aber; es scheint in den meisten Fällen zu funktionieren. Beachten Sie, dass dies zu einem SqlException anstelle eines OperationCancelledException führen kann, wenn der Vorgang ausgeführt wird; Dies ist wiederum auf den ADO.NET-Anbieter zurückzuführen, macht aber sehr viel Sinn: Sie könnten etwas Wichtiges unterbrochen haben; Es tritt als kritisches Verbindungsproblem auf.

Was die Fragen:

Warum ist das Snippet vollständig bebaubare unter der Annahme, dass es auf der gesamten Lösung keinen Compiler-Fehler ist?

Weil ... es C# gültig ist, auch wenn es nicht das tut, was Sie erwarten.

Verzeihen Sie mir, wie ich nicht testen kann, ob das Aufrufen von tokenSource.Cancel() die Methode wirklich abbrechen würde, weil ich nicht weiß, wie man lange laufende SQL-Abfrage erzeugt. Wird die Methode .Cancel() die Methode wirklich abbrechen und OperationCancelledException?

ADO.NET-Provider-spezifische, aber ja, es funktioniert normalerweise. Als ein Beispiel für "wie lange SQL-Abfrage zu generieren"; Der Befehl waitfor delay auf dem SQL-Server ist hier etwas nützlich, und das ist, was ich in den Integrationstests verwende.

+1

Dies ist eine großartige Antwort vom Autor selbst. Danke Marc für die alternative API! Nun, mir geht es gut, wenn ich 'SqlException' statt 'OperationCancelledException' abfange, ich werde hier mit der Logik umgehen. Danke noch einmal! – Pedigree

+1

@Pedigree I * denke * Ich habe auch herausgefunden, wie es auch in der primären API funktioniert. –

+0

Ich habe eine andere Frage marc und ich weiß nicht, ob das noch im Bereich ist, warum haben Sie '.ConfigureAwait (false)' auf * Zeile 78 * von [Datei: SqlMapperAsync.cs] (https: // github.com/StackExchange/dapper-dot-net/blob/master/Dapper%20NET45/SqlMapperAsync.cs)? Was bedeutet das wirklich? Vielen Dank. – Pedigree

1

Sie können SqlMapper.cs in Dapper lib beheben, indem Sie folgende Zeilen:

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 

Ihren eigenen Dapper lib neu erstellen und :)