Поделиться через


Асинхронное программирование

Асинхронные операции не блокируют поток во время выполнения запроса в базе данных. Асинхронные операции важны для обеспечения адаптивного пользовательского интерфейса в расширенных клиентских приложениях, а также могут увеличить пропускную способность в веб-приложениях, где они освобождают поток для обслуживания других запросов в веб-приложениях.

После стандарта .NET EF Core предоставляет асинхронные аналоги для всех синхронных методов, выполняющих операции ввода-вывода. Они имеют те же эффекты, что и методы синхронизации, и могут использоваться с ключевыми словами async C# и await. Например, вместо использования DbContext.SaveChanges, который блокирует поток во время выполнения операций ввода-вывода базы данных, можно использовать DbContext.SaveChangesAsync:

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

Для получения дополнительной информации см. общую документацию по асинхронному программированию на C#.

Предупреждение

EF Core не поддерживает несколько параллельных операций, выполняемых в одном экземпляре контекста. Перед началом следующей операции всегда следует ждать завершения операции. Обычно это делается с помощью ключевого слова await для каждой асинхронной операции.

Предупреждение

Асинхронная реализация Microsoft.Data.SqlClient, к сожалению, имеет некоторые известные проблемы (например, #593, #601и другие). Если возникают непредвиденные проблемы с производительностью, попробуйте использовать выполнение команды синхронизации, особенно при работе с большим текстом или двоичными значениями.

Заметка

EF Core передает маркеры отмены задействованному поставщику базы данных (например, Microsoft.Data.SqlClient). Эти токены могут быть учитываться или не учитываться — обратитесь к документации вашего поставщика базы данных.

Асинхронные операторы LINQ

Для асинхронной поддержки выполнения запросов LINQ EF Core предоставляет набор асинхронных методов расширения, которые выполняют запрос и возвращают результаты. Эти аналоги стандартных синхронных операторов LINQ включают ToListAsync, SingleAsync, AsAsyncEnumerableи т. д.:

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

Обратите внимание, что нет асинхронных версий некоторых операторов LINQ, таких как Where или OrderBy, так как они создают только дерево выражений LINQ и не вызывают выполнение запроса в базе данных. Только операторы, вызывающие выполнение запросов, имеют асинхронные аналоги.

Важный

Асинхронные методы расширения EF Core определяются в пространстве имен Microsoft.EntityFrameworkCore. Пространство имен должно быть импортировано, чтобы методы стали доступными.

Операторы асинхронного LINQ на стороне клиента

В некоторых случаях может потребоваться применить операторы LINQ на стороне клиента, чтобы получить результаты, возвращаемые из базы данных; это особенно необходимо, если необходимо выполнить операцию, которая не может быть переведена в SQL. В таких случаях используйте AsAsyncEnumerable для выполнения запроса в базе данных и продолжайте создавать клиентские операторы LINQ через результирующий IAsyncEnumerable<T>. Например, следующая функция выполняет локальную функцию .NET в асинхронных результатах запроса EF LINQ:

var blogs = context.Blogs
    .Where(b => b.Rating > 3) // server-evaluated (translated to SQL)
    .AsAsyncEnumerable()
    .Where(b => SomeLocalFunction(b)); // client-evaluated (in .NET)

await foreach (var blog in blogs)
{
    // ...
}

Заметка

Операторы LINQ для IAsyncEnumerable<T> были введены в .NET 10. При использовании более старой версии .NET воспользуйтесь пакетом System.Linq.Async.