Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Uwaga / Notatka
Tylko od EF6 wzwyż — funkcje, interfejsy API itp. omówione na tej stronie zostały wprowadzone w Entity Framework 6. Jeśli używasz starszej wersji, niektóre lub wszystkie informacje nie mają zastosowania.
Platforma EF6 wprowadziła obsługę asynchronicznego zapytania i zapisu przy użyciu słów kluczowych async i await, które zostały wprowadzone na platformie .NET 4.5. Chociaż nie wszystkie aplikacje mogą korzystać z asynchronii, może służyć do poprawy czasu odpowiedzi klienta i skalowalności serwera podczas obsługi długotrwałych zadań związanych z siecią lub we/wy.
Kiedy naprawdę używać asynchroniczności
Celem tego przewodnika jest wprowadzenie pojęć asynchronicznych w sposób, który ułatwia obserwowanie różnicy między asynchronicznym i synchronicznym wykonywaniem programu. Ten przewodnik nie ma na celu zilustrowania żadnego z kluczowych scenariuszy, w których programowanie asynchroniczne zapewnia korzyści.
Programowanie asynchroniczne koncentruje się przede wszystkim na zwalnianiu bieżącego zarządzanego wątku (wątku z uruchomionym kodem platformy .NET) w celu wykonania innej pracy podczas oczekiwania na operację, która nie wymaga czasu obliczeniowego z zarządzanego wątku. Na przykład, podczas gdy aparat bazy danych przetwarza zapytanie, kod platformy .NET nie ma nic do zrobienia.
W aplikacjach klienckich (WinForms, WPF itp.) bieżący wątek może być użyty do utrzymania responsywności interfejsu użytkownika podczas wykonywania operacji asynchronicznej. W aplikacjach serwerowych (ASP.NET itp.) wątek może służyć do przetwarzania innych żądań przychodzących — może to zmniejszyć użycie pamięci i/lub zwiększyć przepływność serwera.
W większości aplikacji korzystających z async nie będą miały zauważalnych korzyści, a nawet mogą być szkodliwe. Użyj testów, profilowania i zdrowego rozsądku, aby zmierzyć wpływ asynchronicznego działania w konkretnym scenariuszu przed jego zatwierdzeniem.
Poniżej przedstawiono kilka dodatkowych zasobów, aby dowiedzieć się więcej na temat async:
- Przegląd async/await w .NET 4.5 autorstwa Brandona Braya
- Strony programowania asynchronicznego w bibliotece MSDN
Tworzenie modelu
Użyjemy przepływu pracy Code First , aby utworzyć nasz model i wygenerować bazę danych, jednak funkcja asynchroniczna będzie działać ze wszystkimi modelami EF, w tym modelami utworzonymi w programie EF Designer.
- Tworzenie aplikacji konsolowej i wywoływanie jej asyncDemo
- Dodawanie pakietu NuGet EntityFramework
- W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy projekt AsyncDemo
- Wybierz pozycję Zarządzaj pakietami NuGet...
- W oknie dialogowym Zarządzanie pakietami NuGet wybierz kartę Online i wybierz pakiet EntityFramework
- Kliknij pozycję Zainstaluj
- Dodaj klasę Model.cs z następującą implementacją
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; }
}
}
Tworzenie programu synchronicznego
Teraz, gdy mamy model EF, napiszmy kod, który używa go do wykonywania dostępu do danych.
- Zastąp zawartość Program.cs następującym kodem
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);
}
}
}
}
}
Ten kod wywołuje metodę PerformDatabaseOperations , która zapisuje nowy blog w bazie danych, a następnie pobiera wszystkie blogi z bazy danych i drukuje je w konsoli. Następnie program zapisuje cytat dnia na Console.
Ponieważ kod jest synchroniczny, możemy obserwować następujący przepływ wykonywania podczas uruchamiania programu:
-
SaveChangesrozpoczyna wypychanie nowego bloga do bazy danych -
SaveChangesKończy się - Zapytanie dotyczące wszystkich blogów jest wysyłane do bazy danych
- Zapytania oraz ich wyniki są zapisywane w konsoli
- Cytat dnia jest zapisywany w Konsoli
Uczynienie tego asynchronicznym
Teraz, gdy mamy już uruchomiony program, możemy rozpocząć korzystanie z nowych słów kluczowych async i await. Wprowadziliśmy następujące zmiany w Program.cs
- Wiersz 2: Instrukcja using dla
System.Data.Entityprzestrzeni nazw daje nam dostęp do metod rozszerzenia asynchronicznego EF. - Wiersz 4. Instrukcja using dla przestrzeni nazw
System.Threading.Tasksumożliwia korzystanie z typuTask. - Wiersz 12 i 18: Tworzymy zadanie, które monitoruje postęp
PerformSomeDatabaseOperations(wiersz 12), a następnie blokujemy wykonywanie programu, aby to zadanie mogło się zakończyć, gdy cała praca dla programu zostanie wykonana (wiersz 18). - Linia 25: Zaktualizowaliśmy
PerformSomeDatabaseOperations, aby była oznaczona jakoasynci zwracałaTask. - Wiersz 35: Teraz wywołujemy wersję asynchroniczną
SaveChangesi oczekujemy jej zakończenia. - Wiersz 42: Teraz wywołujemy asynchroniczną wersję
ToListi czekamy na wynik.
Aby uzyskać kompleksową listę dostępnych metod rozszerzeń w System.Data.Entity przestrzeni nazw, zapoznaj się z klasą QueryableExtensions .
Musisz również dodać using System.Data.Entity do instrukcji 'using'.
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);
}
}
}
}
}
Teraz, gdy kod jest asynchroniczny, możemy obserwować inny przepływ wykonywania podczas uruchamiania programu:
-
SaveChangesrozpoczyna wypychanie nowego bloga do bazy danych
Po wysłaniu polecenia do bazy danych nie jest potrzebny już czas obliczeniowy na bieżącym wątku zarządzanym. MetodaPerformDatabaseOperationszwraca (mimo że jej wykonywanie nie zostało zakończone), a przepływ programu w metodzie Main jest kontynuowany. -
Cytat dnia jest zapisywany w konsoli
Ponieważ nie ma więcej pracy do wykonania w metodzie Main, zarządzany wątek jest zablokowany na wywołaniuWaitdo momentu zakończenia operacji bazy danych. Po zakończeniu reszta naszegoPerformDatabaseOperationszostanie wykonana. -
SaveChangesKończy się - Zapytanie dotyczące wszystkich blogów jest wysyłane do bazy danych
Ponownie zarządzany wątek jest wolny do wykonywania innych czynności podczas przetwarzania zapytania w bazie danych. Ponieważ wszystkie inne zadania zostały ukończone, wątek zatrzyma się jednak na wywołaniu Wait. - Zapytania oraz ich wyniki są zapisywane w konsoli
Kluczowa informacja
Widzieliśmy teraz, jak łatwo jest korzystać z asynchronicznych metod EF. Chociaż zalety asynchroniczne mogą nie być bardzo widoczne w prostej aplikacji konsolowej, te same strategie mogą być stosowane w sytuacjach, gdy długotrwałe lub związane z siecią działania mogą w przeciwnym razie blokować aplikację lub powodować dużą liczbę wątków w celu zwiększenia zużycia pamięci.