Frage

Es gibt einige Artikel, die darauf hinweisen, dass asynchrone Datenbankaufrufe in .NET keine gute Idee sind.

Auf C# Async CTP gibt es eine System.Data.SqlClient.SqlCommand Erweiterung aufgerufen ExecuteReaderAsync.Ich habe einige Vorgänge wie folgt für meinen vorhandenen Code:

var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["hubConnectionString"].ConnectionString;

using (var conn = new SqlConnection(connectionString)) {
    using (var cmd = new SqlCommand()) {

        cmd.Connection = conn;
        cmd.CommandText = "sp$DetailsTagsGetAllFromApprovedPropsWithCount";
        cmd.CommandType = System.Data.CommandType.StoredProcedure;

        conn.Open();

        var reader = cmd.ExecuteReader();
        while (reader.Read()) {

            //do the reading

        }

        conn.Close();
    }
}

In meinem Code gibt es mehrere Vorgänge dieser Art.Daher denke ich darüber nach, diese in asynchron umzuwandeln.

Aber andererseits sehe ich bei diesem Ansatz nicht viel Anziehungskraft (vielleicht schaue ich nicht in die richtige Richtung, wer weiß!).

Hat die Verwendung dieses neuen asynchronen Programmiermodells hier irgendwelche Nachteile?

Bearbeiten:

Angenommen, ich überarbeite den Code wie folgt:

public async Task<IEnumerable<Foo>> GetDataAsync() { 

    List<Foo> foos = new List<Foo>();

    var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["hubConnectionString"].ConnectionString;

    using (var conn = new SqlConnection(connectionString)) {
        using (var cmd = new SqlCommand()) {

            cmd.Connection = conn;
            cmd.CommandText = "sp$DetailsTagsGetAllFromApprovedPropsWithCount";
            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            conn.Open();

            var reader = await cmd.ExecuteReaderAsync();
            while (reader.Read()) {

                //do the reading
                //create foos

            }

            conn.Close();
        }
    }

    return foos;

}

Soweit ich das Schlüsselwort „await“ verstehe, konvertiert es den darauf folgenden Code als Fortsetzung.Wenn das Schlüsselwort „await“ aufgerufen wird, kehrt es außerdem unabhängig vom Operationsstatus sofort zu seinem Aufrufer zurück.Wenn es fertig ist, kommt es zurück und löst den Fortsetzungscode aus.

Das ist es, was ich im Sinn habe.

War es hilfreich?

Lösung

Da stimme ich nicht mit Ricka überein.Async-DB-Befehle sind nicht nur gut, sie sind auch entscheidend für die Erzielung von Skalierung und Durchsatz Und Latenz.Sein Einwand bezüglich der Hochlaufzeit des Thread-Pools gilt nur für einen Webserver mit geringem Datenverkehr.

In einer Situation mit hohem Datenverkehr (die die einzige ist, die zählt) muss der Thread-Pool nicht auf das „Injizieren“ neuer Threads warten.Die asynchrone Ausführung der SQL-Befehle ist nicht nur im Hinblick auf die Integrität von Webserver-Anfragen/Threads wichtig, sondern auch im Hinblick auf die gesamte Lebensdauer/Latenz der Anfrage:Unkorrelierte DB-Aufrufe können parallel und nicht sequentiell erfolgen.Dies allein führt in der Regel zu dramatischen Verbesserungen der vom Benutzer erlebten Latenz der HTTP-Anfrage.Mit anderen Worten: Ihre Seiten werden schneller geladen.

Ein Ratschlag jedoch:SQL Command ist erst dann wirklich asynchron, wenn Sie es aktivieren Asynchronous Processing=true auf der Verbindungszeichenfolge.Obwohl dies nicht festgelegt ist (und dies standardmäßig auch nicht der Fall ist), Bearbeiten:beginnend mit .NET Framework < 4.5. Asynchronous Processing ist nicht mehr erforderlich) Ihre „asynchronen“ Aufrufe an BeginExecuteReader sind nichts anderes als eine Täuschung, der Aufruf wird einen Thread starten und blockieren Das Faden.Wenn echte asynchrone Verarbeitung aktiviert ist in der Verbindungszeichenfolge dann ist der Aufruf wirklich asynchron und der Rückruf basiert auf dem E/A-Abschluss.

Ein Wort der Vorsicht:Ein asynchroner SQL-Befehl wird abgeschlossen, sobald der Erste Das Ergebnis wird an den Client zurückgegeben und Infonachrichten zählen als Ergebnis.

create procedure usp_DetailsTagsGetAllFromApprovedPropsWithCount
as
begin
print 'Hello';
select complex query;
end

Sie haben alle Vorteile von Async verloren.Der print Erstellt ein Ergebnis, das an den Client zurückgesendet wird, der den asynchronen Befehl abschließt und die Ausführung auf dem Client fortsetzt und mit „reader.Read()“ fortfährt.Jetzt Das wird blockiert, bis die komplexe Abfrage beginnt, Ergebnisse zu liefern.Du fragst „Wer legt print im Verfahren?' aber die print kann in etwas anderem getarnt sein, vielleicht in etwas so Unschuldigem wie einem INSERT das ausführt ohne erste Ausgabe einer SET NOCOUNT ON.

Andere Tipps

Mir ist aufgefallen, dass die folgende Frage nicht beantwortet wurde:

Hat die Verwendung dieses neuen asynchronen Programmiermodells hier irgendwelche Nachteile?

Der Nachteil welches ist sehr minimal (kleinere CPU/kleinerer Speicher afaik), liegt daran, dass die Möglichkeit besteht, dass nach einer Wait-Anweisung Code ausgeführt wird Mai Bei der Ausführung in einem separaten Thread existiert eine Zustandsmaschine, die den Status des aktuell ausgeführten Threads speichert, sodass die Fortsetzung der Arbeit in einem anderen Thread abgewickelt werden kann.Sie können mehr darüber lesen „await/async statemachine“ auf Dixins Blog – Grundlegendes zur C#-async/await (1)-Kompilierung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top