[翻譯 EF Core in Action 2.4] 加載相關數據

Entity Framework Core in Action

Entityframework Core in action是 Jon P smith 所著的關於Entityframework Core 書籍。原版地址. 是除了官方文檔外另外一個學習EF Core的不錯途徑, 書中由淺入深的講解的EF Core的相關知識。由於沒有中文版,因此本人對其進行翻譯。 預計每兩天一篇更新 PS: 翻譯不免限於本人水平有不許確的地方,建議英文水平不錯的同窗直接查看原版,有不足的地方歡迎指正html

第一部分目錄導航

加載相關數據

以前我向你展現了Book實體類,它有其餘三個實體的導航屬性: PriceOffer,Review和BookAuthor. 下面介紹如何使用代碼訪問這些數據. 你有如下方式加載數據: 貪婪加載,顯式加載,選擇加載和懶加載(在EF Core 2.1中)sql

有一點很重要,EF Core默認不會加載實體類的任何關係(導航屬性),若是加載了Book類,在默認狀況下Book實體的每一個導航屬性都爲null數據庫

默認不加載任何關係的行爲是正確的,這意味着EF Core最小化了數據庫訪問. 若是你想加載一個關係則添加須要代碼告訴EF Core. 下面介紹三種方法,以及它們的優缺點性能

貪婪加載: 加載與主實體類的關係

加載相關數據的第一種方法是貪婪加載. 貪婪加載須要告訴EF Core在加載主實體數據的查詢中加載導航屬性. 使用兩個方法Include和ThenInClude指定預先加載. 下個清單展現了Book實體類實例查詢Books表的第一行數據以及貪婪加載單個關係Reviews學習

  • EF6 EF Core的貪婪加載與EF 6.x的方法相似, 但EF Core改進了語法和SQL實現. EF 6.x沒有ThenInclude方法, 而且EF 6.x的sql實現是嘗試在一個查詢中加載全部數據和集合,這樣的SQL查詢極可能是低效的. EF Core在一個單獨的查詢中加載集合,你能夠在前面的SQL部分看到這一點

下面咱們看一個更復雜的例子,下面的清單展現了查詢第一本書而且貪婪加載它全部的關係.翻譯

以前展現了使用貪婪加載方法Include獲取AuthorsLink關係(一級關係),直接由加載的實體類引用的關係. Include後面使用ThenInclude加載二級關係,本例中是BookAuthor的Author表. 這種方式(Include後面使用ThenInclude)是訪問深層次關係的標準方法,你可使用更多的ThenInclude深刻更深的關係3d

若是數據不存在,好比Book類的Promotion屬性指向的可選PriceOffer類,Include不會失敗,它只是加載不到任何東西,若是是集合會返回一個空集合. ThenInclude也是這樣. 若是前面的Include或Theninclude爲空,後面的ThenInclude會被忽略code

貪婪加載的缺點是會加載全部的數據,有時你不須要某些部分數據,例如圖書列表不須要書籍描述,而圖書描述通常會很長.htm

注: 在EF Core2.0中,若是你在查詢中使用了沒必要要的Include方法,則會有一個警告,好比 context.Books.Include(b => b.Promotion).Where( b => b.Promotion.NewPrice > 10).Select(b => b.BookId) 代碼中使用了include,但它是沒必要要的,由於查詢只返回了BookId. EF Core團隊爲此狀況添加了警告,由於沒有必要使用Inlcude方法.blog

顯式加載: 在加載了實體類以後加載關係

第二個方法是顯式加載,加載了主實體類以後,使用顯式加載其餘所需的關係. 下面的代碼首先加載了書籍,而後使用顯式加載命令讀取全部關係

顯式加載有一個額外的命令,在加載數據的同時而且可用查詢. 下面的代碼展現了使用顯式加載方法Query命令查詢評論數量並加載每一個評論的全部星級評分. 你能夠在Query方法後使用LINQ命令,例如Where,Orderby等

顯式加載的優勢是不會當即加載實體的關係. 這對於在某些狀況下須要相關數據,顯式加載會頗有用. 你還會發如今複雜業務邏輯中顯式加載也頗有用

顯式加載的缺點是會產生更多的數據庫往返,這多是低效的. 若是你事先知道所需的數據,那麼貪婪加載一般會更好,由於加載關係所需的數據庫往返次數更少

選擇加載: 加載實體類的特定屬性和關係

第三種方法是使用LINQ的Select方法明確的選擇須要的數據,我稱之爲選擇加載. 下面展現了使用Select方法從Book類中選擇屬性,在查詢中執行特定的代碼獲取書的評論數量

Select查詢方法的優勢是隻加載你須要的數據,在你不須要全部的數據時,這會頗有用. 上面的查詢代碼只須要一個Select SQL命令獲取全部數據. 在數據庫往返次數方面也不多. EF Core將查詢的p.Reviews.Count轉換爲SQL命令,在數據庫中完成計數. 以下面的SQL所示

SELECT TOP(1) [p].[Title], [p].[Price], ( 
       SELECT COUNT(*)  
       FROM [Review] AS [r0] 
       WHERE [p].[BookId] = [r0].[BookId] ) 
       FROM [Books] AS [p]

選擇加載的缺點是須要爲每一個屬性/計算編寫代碼. 這會很繁瑣, 在10.3節中我介紹了一種自動化的方法

注: 在本章的後面,你會看到更復雜的選擇加載案例,咱們會使用這種類型的加載構建圖書應用程序的圖書列表查詢

EF Core 2.1中的延遲加載

在EF 6.x中將屬性標記爲virtual,在讀取到該屬性時會進行數據庫訪問. 延遲加載添加到了EF Core 2.1中

喜歡延遲加載的人說,延遲加載很容易使用,在讀取屬性時不須要應用程序數據庫上下文. 延遲加載的缺點是對延遲加載的數據進行更多的數據庫訪問. 讓查詢變慢, 本章描述的三種方法在我看來徹底能夠消除延遲加載的存在乎義,它們能夠帶來性能更高的數據庫訪問

相關文章
相關標籤/搜索