다음을 통해 공유


비동기 프로그래밍

비동기 작업은 쿼리가 데이터베이스에서 실행되는 동안 스레드를 차단하지 않습니다. 비동기 작업은 풍부한 클라이언트 애플리케이션에서 응답성이 뛰어난 UI를 유지하는 데 중요하며, 웹 애플리케이션에서 스레드를 확보하여 웹 애플리케이션의 다른 요청을 처리할 수 있는 처리량을 늘릴 수도 있습니다.

.NET 표준에 따라 EF Core는 I/O를 수행하는 모든 동기 메서드에 비동기 대응 메서드를 제공합니다. 동기화 메서드와 동일한 효과를 가지며 C# asyncawait 키워드와 함께 사용할 수 있습니다. 예를 들어 데이터베이스 I/O가 수행되는 동안 스레드를 차단하는 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();

Where 또는 OrderBy같은 일부 LINQ 연산자의 비동기 버전은 없습니다. LINQ 식 트리만 빌드하고 데이터베이스에서 쿼리를 실행하지 않기 때문입니다. 쿼리 실행을 유발하는 연산자만 비동기 대응을 갖습니다.

중요하다

EF Core 비동기 확장 메서드는 Microsoft.EntityFrameworkCore 네임스페이스에 정의됩니다. 메서드를 사용할 수 있도록 이 네임스페이스를 가져와야 합니다.

클라이언트 쪽 비동기 LINQ 연산자

경우에 따라 데이터베이스에서 돌아오는 결과에 클라이언트 쪽 LINQ 연산자를 적용할 수 있습니다. SQL로 변환할 수 없는 작업을 수행해야 하는 경우에 특히 필요합니다. 이러한 경우 AsAsyncEnumerable 사용하여 데이터베이스에서 쿼리를 실행하고 결과 IAsyncEnumerable<T>대해 클라이언트 쪽 LINQ 연산자를 계속 작성합니다. 예를 들어 다음에서는 EF LINQ 쿼리의 비동기 결과에 대해 로컬 .NET 함수를 실행합니다.

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)
{
    // ...
}

메모

IAsyncEnumerable<T> LINQ 연산자는 .NET 10에 도입되었습니다. 이전 버전의 .NET을 사용하는 경우 System.Linq.Async 패키지참조합니다.