Programowanie asynchroniczne

Operacje asynchroniczne unikają blokowania wątku podczas wykonywania zapytania w bazie danych. Operacje asynchroniczne są ważne w celu utrzymania dynamicznego interfejsu użytkownika w zaawansowanych aplikacjach klienckich, a także mogą zwiększyć przepływność w aplikacjach internetowych, w których zwalniają wątki do obsługi innych żądań w aplikacjach internetowych.

Zgodnie ze standardem .NET, program EF Core udostępnia asynchroniczne odpowiedniki do wszystkich metod synchronicznych, które wykonują operacje we/wy. Mają one takie same efekty jak metody synchronizacji i mogą być używane z językiem C# async i await słowami kluczowymi. Na przykład zamiast używać polecenia DbContext.SaveChanges, co spowoduje zablokowanie wątku podczas wykonywania operacji we/wy bazy danych, można użyć polecenia DbContext.SaveChangesAsync:

var blog = new Blog { Url = "http://sample.com" };
context.Blogs.Add(blog);
await context.SaveChangesAsync();

Aby uzyskać więcej informacji, zobacz ogólne dokumenty dotyczące programowania asynchronicznego języka C#.

Ostrzeżenie

Program EF Core nie obsługuje wielu równoległych operacji uruchamianych w tym samym wystąpieniu kontekstu. Przed rozpoczęciem następnej operacji należy zawsze czekać na ukończenie operacji. Zazwyczaj odbywa się to przy użyciu słowa kluczowego await dla każdej operacji asynchronicznych.

Ostrzeżenie

Implementacja asynchronicznego elementu Microsoft.Data.SqlClient niestety ma pewne znane problemy (np. #593, #601 i inne). Jeśli występują nieoczekiwane problemy z wydajnością, spróbuj zamiast tego użyć polecenia synchronizacji, szczególnie w przypadku obsługi dużych wartości tekstowych lub binarnych.

Uwaga

Program EF Core przekazuje tokeny anulowania do używanego dostawcy baz danych (np. Microsoft.Data.SqlClient). Te tokeny mogą lub nie są honorowane — zapoznaj się z dokumentacją dostawcy bazy danych.

Asynchroniczne operatory LINQ

Aby umożliwić asynchroniczne wykonywanie zapytań LINQ, program EF Core udostępnia zestaw metod rozszerzenia asynchronicznego, które wykonują zapytanie i zwracają wyniki. Te odpowiedniki standardowych, synchronicznych operatorów LINQ to ToListAsync, SingleAsync, AsAsyncEnumerableitp.:

var blogs = await context.Blogs.Where(b => b.Rating > 3).ToListAsync();

Należy pamiętać, że nie ma żadnych asynchronicznych wersji niektórych operatorów LINQ, takich jak Where lub OrderBy, ponieważ tworzą one tylko drzewo wyrażeń LINQ i nie powodują wykonywania zapytania w bazie danych. Tylko operatory, które powodują wykonywanie zapytania, mają odpowiedniki asynchroniczne.

Ważne

Metody rozszerzenia asynchronicznego platformy EF Core są definiowane Microsoft.EntityFrameworkCore w przestrzeni nazw. Ta przestrzeń nazw musi zostać zaimportowana, aby metody są dostępne.

Asynchroniczne operatory LINQ po stronie klienta

Asynchroniczne operatory LINQ omówione powyżej mogą być używane tylko w zapytaniach EF — nie można ich używać z zapytaniem LINQ to Objects po stronie klienta. Aby wykonać operacje asynchroniczne LINQ po stronie klienta poza programem EF, użyj System.Linq.Async pakietu. Ten pakiet może być szczególnie przydatny do wykonywania operacji na kliencie, których nie można przetłumaczyć na potrzeby oceny na serwerze.

W programie EF Core 6.0 i niższym odwołaniu System.Linq.Async się niestety powoduje niejednoznaczne błędy kompilacji wywołań na operatorach LINQ zastosowanych do zestawów DBSet platformy EF. Utrudnia to korzystanie zarówno z platformy EF, jak i System.Linq.Async w tym samym projekcie. Aby obejść ten problem, dodaj AsQueryable element do zestawu dbSet:

var groupedHighlyRatedBlogs = await context.Blogs
    .AsQueryable()
    .Where(b => b.Rating > 3) // server-evaluated
    .AsAsyncEnumerable()
    .GroupBy(b => b.Rating) // client-evaluated
    .ToListAsync();