Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Nur EF6 und höher: Die Features, APIs usw., die auf dieser Seite erläutert werden, wurden in Entity Framework 6 eingeführt. Wenn Sie eine frühere Version verwenden, gelten einige oder alle Informationen nicht.
EF6 hat Unterstützung für asynchrone Abfragen und Speichern eingeführt, mithilfe der Schlüsselwörter async und await, die in .NET 4.5 eingeführt wurden. Nicht alle Anwendungen profitieren von Asynchronität, aber sie kann verwendet werden, um die Reaktionsfähigkeit des Clients und die Serverskalierbarkeit bei der Behandlung von langen Ausführungs-, Netzwerk- oder E/A-gebundenen Aufgaben zu verbessern.
Wann soll asynchron verwendet werden?
In dieser exemplarischen Vorgehensweise werden die asynchronen Konzepte auf eine Weise eingeführt, mit der der Unterschied zwischen asynchroner und synchroner Programmausführung leicht zu beobachten ist. Diese exemplarische Vorgehensweise soll keines der wichtigsten Szenarien veranschaulichen, in denen die asynchrone Programmierung Vorteile bietet.
Die asynchrone Programmierung konzentriert sich in erster Linie darauf, den aktuellen verwalteten Thread (Thread mit .NET-Code) freizugeben, um andere Aufgaben auszuführen, während er auf einen Vorgang wartet, der keine Berechnungszeit von einem verwalteten Thread erfordert. Während das Datenbankmodul beispielsweise eine Abfrage verarbeitet, gibt es nichts, das von .NET-Code ausgeführt werden muss.
In Clientanwendungen (WinForms, WPF usw.) kann der aktuelle Thread verwendet werden, um die Benutzeroberfläche reaktionsfähig zu halten, während der asynchrone Vorgang ausgeführt wird. In Serveranwendungen (ASP.NET usw.) kann der Thread zum Verarbeiten anderer eingehender Anforderungen verwendet werden. Dies kann die Speicherauslastung reduzieren und/oder den Durchsatz des Servers erhöhen.
In den meisten Anwendungen, bei der Verwendung von async, gibt es keine spürbaren Vorteile und es kann sogar nachteilig sein. Verwenden Sie Tests, Profilerstellung und gesunden Menschenverstand, um die Auswirkungen von Asynchronität in Ihrem jeweiligen Szenario zu messen, bevor Sie sich darauf festlegen.
Hier finden Sie einige weitere Ressourcen, um mehr über asynchrone Programmierung zu erfahren:
- Brandon Brays Übersicht über async/await in .NET 4.5
- Asynchrone Programmierseiten in der MSDN Library
Erstellen des Modells
Wir verwenden den Code First-Workflow , um unser Modell zu erstellen und die Datenbank zu generieren. Die asynchrone Funktionalität funktioniert jedoch mit allen EF-Modellen, einschließlich derjenigen, die mit dem EF Designer erstellt wurden.
- Erstellen einer Konsolenanwendung und Aufrufen von "AsyncDemo"
- Hinzufügen des EntityFramework NuGet-Pakets
- Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das AsyncDemo-Projekt .
- Wählen Sie „NuGet-Pakete verwalten…“
- Wählen Sie im Dialogfeld "NuGet-Pakete verwalten" die Registerkarte "Online " und dann das EntityFramework-Paket aus.
- Klicken Sie auf Install (Installieren).
- Hinzufügen einer Model.cs Klasse mit der folgenden Implementierung
using System.Collections.Generic;
using System.Data.Entity;
namespace AsyncDemo
{
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public virtual Blog Blog { get; set; }
}
}
Erstellen eines synchronen Programms
Nachdem wir nun über ein EF-Modell verfügen, schreiben wir code, der ihn zum Ausführen eines Datenzugriffs verwendet.
- Ersetzen Sie den Inhalt von Program.cs durch den folgenden Code.
using System;
using System.Linq;
namespace AsyncDemo
{
class Program
{
static void Main(string[] args)
{
PerformDatabaseOperations();
Console.WriteLine("Quote of the day");
Console.WriteLine(" Don't worry about the world coming to an end today... ");
Console.WriteLine(" It's already tomorrow in Australia.");
Console.WriteLine();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
public static void PerformDatabaseOperations()
{
using (var db = new BloggingContext())
{
// Create a new blog and save it
db.Blogs.Add(new Blog
{
Name = "Test Blog #" + (db.Blogs.Count() + 1)
});
Console.WriteLine("Calling SaveChanges.");
db.SaveChanges();
Console.WriteLine("SaveChanges completed.");
// Query for all blogs ordered by name
Console.WriteLine("Executing query.");
var blogs = (from b in db.Blogs
orderby b.Name
select b).ToList();
// Write all blogs out to Console
Console.WriteLine("Query completed with following results:");
foreach (var blog in blogs)
{
Console.WriteLine(" " + blog.Name);
}
}
}
}
}
Dieser Code ruft die Methode auf, mit der PerformDatabaseOperations ein neuer Blog in der Datenbank gespeichert wird, und ruft dann alle Blogs aus der Datenbank ab und druckt sie in der Konsole. Danach schreibt das Programm ein Zitat des Tages in die Konsole.
Da der Code synchron ist, können wir den folgenden Ausführungsfluss beobachten, wenn wir das Programm ausführen:
-
SaveChangesbeginnt mit dem Pushen des neuen Blogs an die Datenbank. -
SaveChangesabschließen - Abfrage für alle Blogs wird an die Datenbank gesendet
- Abfrageergebnisse und Resultate werden in die Konsole geschrieben.
- Das Zitat des Tages wird auf die Konsole geschrieben
Asynchrone Erstellung
Nachdem unser Programm nun läuft, können wir mit der Nutzung der neuen async und await Schlüsselwörter beginnen. Wir haben die folgenden Änderungen an der Datei Program.cs vorgenommen.
- Zeile 2: Die using-Anweisung für den
System.Data.EntityNamespace gibt uns Zugriff auf die EF asynchronen Erweiterungsmethoden. - Zeile 4: Die using-Anweisung für den
System.Threading.TasksNamespace ermöglicht es uns, denTaskTyp zu verwenden. - Zeile 12 & 18: Wir erfassen eine Aufgabe, die den Fortschritt von
PerformSomeDatabaseOperations(Zeile 12) überwacht und blockieren dann die Programmausführung, bis diese Aufgabe abgeschlossen ist, nachdem alle Arbeiten für das Programm erledigt sind (Zeile 18). - Zeile 25: Wir haben
PerformSomeDatabaseOperationsaktualisiert, damit es alsasyncgekennzeichnet wird undTaskzurückgibt. - Zeile 35: Wir rufen jetzt die asynchrone Version von
SaveChangesauf und warten auf den Abschluss. - Zeile 42: Wir rufen jetzt die Asynchrone Version von
ToListund warten auf das Ergebnis.
Eine umfassende Liste der verfügbaren Erweiterungsmethoden im System.Data.Entity Namespace finden Sie in der QueryableExtensions Klasse.
Außerdem müssen Sie using System.Data.Entity zu Ihren using-Anweisungen hinzufügen.
using System;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
namespace AsyncDemo
{
class Program
{
static void Main(string[] args)
{
var task = PerformDatabaseOperations();
Console.WriteLine("Quote of the day");
Console.WriteLine(" Don't worry about the world coming to an end today... ");
Console.WriteLine(" It's already tomorrow in Australia.");
task.Wait();
Console.WriteLine();
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
public static async Task PerformDatabaseOperations()
{
using (var db = new BloggingContext())
{
// Create a new blog and save it
db.Blogs.Add(new Blog
{
Name = "Test Blog #" + (db.Blogs.Count() + 1)
});
Console.WriteLine("Calling SaveChanges.");
await db.SaveChangesAsync();
Console.WriteLine("SaveChanges completed.");
// Query for all blogs ordered by name
Console.WriteLine("Executing query.");
var blogs = await (from b in db.Blogs
orderby b.Name
select b).ToListAsync();
// Write all blogs out to Console
Console.WriteLine("Query completed with following results:");
foreach (var blog in blogs)
{
Console.WriteLine(" - " + blog.Name);
}
}
}
}
}
Da der Code asynchron ist, können wir beim Ausführen des Programms einen anderen Ausführungsfluss beobachten:
-
SaveChangesbeginnt mit dem Pushen des neuen Blogs an die Datenbank.
Sobald der Befehl an die Datenbank gesendet wird, ist keine Berechnungszeit für den aktuellen verwalteten Thread erforderlich. DiePerformDatabaseOperationsMethode gibt zurück (auch wenn sie nicht abgeschlossen wurde) und der Programmfluss in der Main-Methode fortgesetzt wird. -
Das Zitat des Tages wird in Konsole geschrieben
Da in der Main-Methode keine weiteren Aufgaben ausgeführt werden müssen, wird der verwaltete Thread für denWaitAufruf blockiert, bis der Datenbankvorgang abgeschlossen ist. Nach Abschluss des Vorgangs wird der Rest unseresPerformDatabaseOperationsVorgangs ausgeführt. -
SaveChangesabschließen - Abfrage für alle Blogs wird an die Datenbank gesendet
Auch hier kann der verwaltete Thread andere Aufgaben ausführen, während die Abfrage in der Datenbank verarbeitet wird. Da alle anderen Ausführungen abgeschlossen sind, wird der Thread beim Wait-Aufruf einfach anhalten. - Abfrageergebnisse und Resultate werden in die Konsole geschrieben.
Die Erkenntnis
Wir haben nun gesehen, wie einfach es ist, die asynchronen Methoden von EF zu nutzen. Obwohl die Vorteile von async bei einer einfachen Konsolen-App möglicherweise nicht sehr offensichtlich sind, können dieselben Strategien in Situationen angewendet werden, in denen lange ausgeführte oder netzwerkgebundene Aktivitäten die Anwendung sonst blockieren oder eine große Anzahl von Threads dazu führen, den Speicherbedarf zu erhöhen.