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