查詢數據
Entity Framework Core 使用語言集成查詢 (LINQ) 來查詢數據庫中的數據。 通過 LINQ 可使用 C#(或你選擇的其他 .NET 語言)基於派生上下文和實體類編寫強類型查詢。 LINQ 查詢的一種表示形式會傳遞給數據庫提供程序,進而轉換為特定於數據庫的查詢語言(例如,適用於關系數據庫的 SQL)。
查詢的生命周期
下面是每個查詢所經歷的過程的高級概述。
- LINQ 查詢由 Entity Framework Core 處理,用於生成已准備好由數據庫提供程序處理的表示形式
- 結果會被緩存,以便每次執行查詢時無需重復進行此處理
- 結果會傳遞到數據庫提供程序
- 數據庫提供程序會識別出查詢的哪些部分可以在數據庫中求值
- 查詢的這些部分會轉換為特定數據庫的查詢語言(例如,關系數據庫的 SQL)
- 一個或多個查詢會發送到數據庫並返回結果集(返回的是數據庫中的值,而不是實體實例中的)
- 對於結果集中的每一項
- 如果這是跟蹤查詢,EF 會檢查數據是否表示上下文實例內更改跟蹤器中的現有實體
- 如果是,則會返回現有實體
- 如果不是,則會創建新實體、設置更改跟蹤並返回該新實體
- 如果這是非跟蹤查詢,EF 會檢查數據是否表示此查詢結果集中的現有實體
- 如果是,則會返回現有實體 (1)
- 如果不是,則會創建新實體並返回該新實體
- 如果這是跟蹤查詢,EF 會檢查數據是否表示上下文實例內更改跟蹤器中的現有實體
(1) 非跟蹤查詢使用弱引用跟蹤已返回的實體。 如果具有相同標識的上一個結果超出范圍,並遇到垃圾回收機制執行,則可能會獲得新的實體實例。
跟蹤與非跟蹤查詢
跟蹤查詢
跟蹤行為可控制 Entity Framework Core 是否將有關實體實例的信息保留在其更改跟蹤器中。 如果已跟蹤某個實體,則該實體中檢測到的任何更改都會在 SaveChanges()
期間永久保存到數據庫。 Entity Framework Core 還會修正從跟蹤查詢中獲取的實體與先前已加載到 DbContext 實例中的實體兩者之間的導航屬性。
默認情況下,跟蹤返回實體類型的查詢。 這表示可以更改這些實體實例,然后通過 SaveChanges()
持久化這些更改。
在以下示例中,將檢測到對博客評分所做的更改,並在 SaveChanges()
期間將這些更改持久化到數據庫中。
using (var context = new BloggingContext()) { var blog = context.Blogs.SingleOrDefault(b => b.BlogId == 1); blog.Rating = 5; context.SaveChanges(); }
非跟蹤查詢
在只讀方案中使用結果時,非跟蹤查詢十分有用。 可以更快速地執行非跟蹤查詢,因為無需設置更改跟蹤信息。
可以交換單個非跟蹤查詢:
using (var context = new BloggingContext()) { var blogs = context.Blogs .AsNoTracking() .ToList(); }
還可以在上下文實例級別更改默認跟蹤行為:
using (var context = new BloggingContext()) { context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; var blogs = context.Blogs.ToList(); }
跟蹤和投影
即使查詢的結果類型不是實體類型,但如果結果包含實體類型,則默認情況下也會跟蹤這些實體類型。 在以下返回匿名類型的查詢中,會跟蹤結果集中 Blog
的實例。
using (var context = new BloggingContext()) { var blog = context.Blogs .Select(b => new { Blog = b, Posts = b.Posts.Count() }); }
如果結果集不包含任何實體類型,則不會執行跟蹤。 在以下返回匿名類型(具有實體中的某些值,但沒有實際實體類型的實例)的查詢中,不會執行跟蹤。
using (var context = new BloggingContext()) { var blog = context.Blogs .Select(b => new { Id = b.BlogId, Url = b.Url }); }
執行查詢時
調用 LINQ 運算符時,只會構建查詢在內存中的表示形式。 只有在使用結果時,查詢才會發送到數據庫。
導致查詢發送到數據庫的最常見操作如下:
- 在
for
循環中循環訪問結果 - 使用
ToList
、ToArray
、Single
、Count
等操作 - 將查詢結果數據綁定到 UI