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


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

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

После стандарта .NET EF Core предоставляет асинхронные аналоги для всех синхронных методов, выполняющих операции ввода-вывода. Они имеют те же эффекты, что и методы синхронизации, и могут использоваться с C# async и 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 можно использовать только в запросах EF. Их нельзя использовать с клиентским запросом LINQ to Objects. Для выполнения асинхронных операций LINQ на стороне клиента за пределами EF используйте System.Linq.Async пакет. Этот пакет может быть особенно полезен для выполнения операций с клиентом, которые не могут быть переведены для оценки на сервере.

В EF Core 6.0 и более низкой ссылки, к System.Linq.Async сожалению, вызывает неоднозначные ошибки компиляции вызовов для операторов LINQ, применяемых к DbSets EF. Это затрудняет использование EF и System.Linq.Async в одном проекте. Чтобы обойти эту проблему, добавьте AsQueryable в DbSet:

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