次の方法で共有


非同期プログラミング

非同期操作では、データベースでクエリが実行されている間にスレッドがブロックされないようにします。 非同期操作は、リッチ クライアント アプリケーションで応答性の高い UI を維持するために重要であり、Web アプリケーションでスレッドを解放して Web アプリケーション内の他の要求にサービスを提供する場合でもスループットを向上させることができます。

.NET 標準に従って、EF Core は、I/O を実行するすべての同期メソッドに対応する非同期メソッドを提供します。 これらは同期方法と同じ効果を持ち、C# async キーワードと await キーワードで使用できます。 たとえば、データベース 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 演算子に対応するこれらの演算子には、ToListAsyncSingleAsyncAsAsyncEnumerableなどがあります。

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

WhereOrderByなどの一部の 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 パッケージを参照してください。