EF Core非同步程式設計

一个人走在路上發表於2024-04-03

非同步程式設計

本文內容
非同步 LINQ 運算子
客戶端非同步 LINQ 運算子
當在資料庫中執行查詢時,非同步操作可避免阻止執行緒。 對於在富客戶端應用程式中保持響應式 UI,非同步操作很重要,還可以增加 Web 應用程式中的吞吐量,從而釋放執行緒來為 Web 應用程式中的其他請求提供服務。

按照 .NET 標準,EF Core 將為所有執行 I/O 的同步方法提供非同步對應項。 它們具有與同步方法相同的效果,並且可與 C# async 和 await 關鍵字結合使用。 例如,不使用在執行資料庫 I/O 時將阻塞執行緒的 DbContext.SaveChanges,而是改為使用 DbContext.SaveChangesAsync:

C#

複製
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 等:

C#

複製
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 查詢。 若要在 EF 之外執行客戶端非同步 LINQ 操作,請使用 System.Linq.Async 包;對於在客戶端上執行無法在伺服器上轉換為評估的操作,此包非常有用。

在 EF Core 6.0 及更低版本中,可惜的是,引用 System.Linq.Async 會導致應用到 EF 的 DbSet 的 LINQ 運算子出現不明確的呼叫編譯錯誤;這使得很難在同一個專案中同時使用 EF 和 System.Linq.Async。 若要解決此問題,請將 AsQueryable 新增到 DbSet:

C#

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

相關文章