Ich habe nach den Unterschieden zwischen 2 Paaren oben gesucht, aber keine Artikel gefunden, die klar erklären, wann und wann ich das eine oder andere verwenden soll.
Was ist der Unterschied zwischen SaveChanges()
und SaveChangesAsync()
?
Und zwischen Find()
und FindAsync()
?
Auf der Serverseite müssen wir bei der Verwendung von Async
Methoden auch hinzufügen await
. Daher denke ich nicht, dass es auf der Serverseite asynchron ist.
Hilft es nur, die Blockierung der Benutzeroberfläche im clientseitigen Browser zu verhindern? Oder gibt es Vor- und Nachteile zwischen ihnen?
c#
entity-framework
async-await
Hien Tran
quelle
quelle
Antworten:
Jedes Mal, wenn Sie eine Aktion auf einem Remote-Server ausführen müssen, generiert Ihr Programm die Anforderung, sendet sie und wartet auf eine Antwort. Ich werde
SaveChanges()
undSaveChangesAsync()
als Beispiel verwenden, aber das gleiche gilt fürFind()
undFindAsync()
.Angenommen, Sie haben eine Liste
myList
mit mehr als 100 Elementen, die Sie Ihrer Datenbank hinzufügen müssen. Um das einzufügen, würde Ihre Funktion ungefähr so aussehen:Zuerst erstellen Sie eine Instanz von
MyEDM
, fügen die ListemyList
der Tabelle hinzuMyTable
und rufen dann auf,SaveChanges()
um die Änderungen an der Datenbank beizubehalten. Es funktioniert wie Sie möchten, die Datensätze werden festgeschrieben, aber Ihr Programm kann nichts anderes tun, bis das Festschreiben abgeschlossen ist. Dies kann lange dauern, je nachdem, was Sie festlegen. Wenn Sie Änderungen an den Datensätzen vornehmen, muss die Entität diese nacheinander festschreiben (ich hatte einmal 2 Minuten Zeit für Aktualisierungen, um sie zu speichern)!Um dieses Problem zu lösen, können Sie eines von zwei Dingen tun. Das erste ist, dass Sie einen neuen Thread starten können, um die Einfügung zu handhaben. Dadurch wird der aufrufende Thread für die weitere Ausführung freigegeben. Sie haben jedoch einen neuen Thread erstellt, der nur dort sitzt und wartet. Es gibt keine Notwendigkeit für diesen Aufwand, und das ist, was die
async await
löst Muster.Für E / A-Operationen wird
await
schnell Ihr bester Freund. Wenn wir den Codeabschnitt von oben nehmen, können wir ihn wie folgt ändern:Es ist eine sehr kleine Änderung, aber es gibt tiefgreifende Auswirkungen auf die Effizienz und Leistung Ihres Codes. Was passiert also? Der Beginn des Codes ist das gleiche, Sie eine Instanz erstellen
MyEDM
und fügen Sie IhremyList
zuMyTable
. Wenn Sie jedoch aufrufenawait context.SaveChangesAsync()
, kehrt die Ausführung des Codes zur aufrufenden Funktion zurück!Während Sie darauf warten, dass alle diese Datensätze festgeschrieben werden, kann Ihr Code weiterhin ausgeführt werden. Angenommen, die Funktion, die den obigen Code enthielt, hatte die Signaturpublic async Task SaveRecords(List<MyTable> saveList)
, die aufrufende Funktion könnte folgendermaßen aussehen:Warum Sie eine solche Funktion haben würden, weiß ich nicht, aber was sie ausgibt, zeigt, wie es
async await
funktioniert. Lassen Sie uns zuerst untersuchen, was passiert.Die Ausführung wird eingegeben
MyCallingFunction
,Function Starting
dannSave Starting
in die Konsole geschrieben und die FunktionSaveChangesAsync()
aufgerufen. Zu diesem Zeitpunkt kehrt die Ausführung zuMyCallingFunction
der for-Schleife zurück und gibt sie bis zu 1000 Mal ein. Wenn derSaveChangesAsync()
Vorgang abgeschlossen ist, kehrt die Ausführung zurSaveRecords
Funktion zurück und schreibtSave Complete
in die Konsole. Sobald allesSaveRecords
abgeschlossen ist, wird die Ausführung in fortgesetztMyCallingFunction
genau dort sie abgeschlossen warSaveChangesAsync()
. Verwirrt? Hier ist eine Beispielausgabe:Oder vielleicht:
Das ist das Schöne daran:
async await
Ihr Code kann weiterhin ausgeführt werden, während Sie darauf warten, dass etwas beendet wird. In Wirklichkeit hätten Sie eine ähnliche Funktion als Ihre aufrufende Funktion:Hier haben Sie vier verschiedene Funktionen zum Speichern von Datensätzen gleichzeitig .
MyCallingFunction
wird viel schneller ausgeführt,async await
als wenn die einzelnenSaveRecords
Funktionen in Reihe aufgerufen würden.Das einzige, was ich noch nicht angesprochen habe, ist das
await
Schlüsselwort. Dadurch wird die Ausführung der aktuellen Funktion gestoppt, bis allesTask
, was Sie erwarten, abgeschlossen ist. Im Fall des OriginalsMyCallingFunction
wird die ZeileFunction Complete
also erst nach Abschluss derSaveRecords
Funktion in die Konsole geschrieben .Kurz gesagt, wenn Sie eine Option zur Verwendung haben
async await
, sollten Sie dies tun, da dies die Leistung Ihrer Anwendung erheblich steigern wird.quelle
await
jedoch verwenden, auch wenn SIE nach dem Aufruf von SaveChanges nichts anderes tun müssen, sagt ASP "aha, dieser Thread wurde zurückgegeben und wartet auf eine asynchrone Operation. Dies bedeutet, dass ich diesen Thread in der Zwischenzeit eine andere Anfrage bearbeiten lassen kann ! " Dadurch wird Ihre App horizontal viel besser skaliert.await
fürSaveChangesAsync
da EF nicht mehrere gleichzeitig spart nicht unterstützt. docs.microsoft.com/en-us/ef/core/saving/async Außerdem bietet die Verwendung dieser asynchronen Methoden einen großen Vorteil. Sie können beispielsweise weiterhin andere Anforderungen in Ihrem webApi empfangen, wenn Sie Daten speichern oder viel Sutuff ausführen, oder die Benutzererfahrung verbessern, ohne die Benutzeroberfläche einzufrieren, wenn Sie sich in einer Desktop-Anwendung befinden.Meine verbleibende Erklärung basiert auf dem folgenden Codefragment.
Fall 1
Anmerkungen: Da sich der synchrone Teil (grün) von
JobAsync
Drehungen länger als die Aufgabet
(rot) dreht, ist die Aufgabet
bereits zum Zeitpunkt abgeschlossenawait t
. Infolgedessen läuft die Fortsetzung (blau) auf demselben Thread wie die grüne. Der synchrone Teil vonMain
(weiß) dreht sich, nachdem der grüne Teil fertig ist. Aus diesem Grund ist der synchrone Teil bei der asynchronen Methode problematisch.Fall 2
Anmerkungen: Dieser Fall ist dem ersten Fall entgegengesetzt. Der synchrone Teil (grün) der
JobAsync
Drehungen, der kürzer als die Aufgabet
(rot) ist, dann ist die Aufgabet
zum Zeitpunkt von noch nicht abgeschlossenawait t
. Infolgedessen läuft die Fortsetzung (blau) auf dem anderen Thread als der grüne. Der synchrone Teil vonMain
(weiß) dreht sich immer noch, nachdem der grüne Teil fertig ist.Fall 3
Anmerkungen: Dieser Fall löst das Problem in den vorherigen Fällen bezüglich des synchronen Teils in der asynchronen Methode. Die Aufgabe
t
wird sofort erwartet. Infolgedessen läuft die Fortsetzung (blau) auf dem anderen Thread als der grüne. Der synchrone Teil vonMain
(weiß) dreht sich sofort parallel zuJobAsync
.Wenn Sie weitere Fälle hinzufügen möchten, können Sie diese jederzeit bearbeiten.
quelle
Diese Aussage ist falsch:
Sie müssen nicht "Warten" hinzufügen. Dies
await
ist lediglich ein praktisches Schlüsselwort in C #, mit dem Sie nach dem Aufruf weitere Codezeilen schreiben können. Diese anderen Zeilen werden erst ausgeführt, nachdem der Speichervorgang abgeschlossen ist. Aber wie Sie bereits betont haben, können Sie dies einfach durch einen Anruf erreichenSaveChanges
stattSaveChangesAsync
.Grundsätzlich geht es bei einem asynchronen Aufruf jedoch um viel mehr. Die Idee hier ist, dass Sie verwenden sollten, wenn Sie andere Arbeiten (auf dem Server) ausführen können, während der Speichervorgang ausgeführt wird
SaveChangesAsync
. Verwenden Sie nicht "Warten". Rufen Sie einfach anSaveChangesAsync
und machen Sie dann parallel andere Dinge weiter. Dies umfasst möglicherweise die Rückgabe einer Antwort an den Client in einer Web-App, noch bevor der Speichervorgang abgeschlossen ist. Aber natürlich möchten Sie immer noch das Endergebnis des Speicherns überprüfen, damit Sie es Ihrem Benutzer mitteilen oder es irgendwie protokollieren können, falls es fehlschlägt.quelle