查缺補漏系統學習 EF Core 6 - 數據查詢

這是 EF Core 系列的第四篇文章,上一篇文章講述了 EF Core 中的實體遷移與數據播種。

這篇文章盤點一下 EF Core 的幾種數據查詢方式,內容較多分上下兩篇。

點擊上方或后方藍字,閱讀 EF Core 系列合集。

4070af2529d7610d2cc16b61360bbae7.png

簡單查詢

在 EF Core 中,每個查詢都由三個主要部分組成:

  • 通過?ApplicationContext?的?DbSet?屬性連接到數據庫

  • 使用一系列的 LINQ 或 EF Core 命令

  • 執行查詢

這是一個最簡單的示例:

public?void?Run()
{var?accounts?=?_context.Accounts.Where(s?=>?s.Age?>?16).ToList();
}

從這個查詢中,我們可以看到查詢的三個主要部分:

「_context.Accounts」?是查詢第一部分,通過?DbSet<Account>?屬性,訪問數據庫中的?Account?表。

「Where(s => s.Age > 25)」?是查詢的第二部分,使用 LINQ 方法篩選需要的行。

最后,「ToList()」?方法用來來執行這個查詢。

需要注意的是,當我們在 EF Core 中編寫只讀查詢時,可以添加?AsNoTracking?方法提高查詢效率:

_context.Accounts.AsNoTracking()

使用 AsNoTracking 方法時,EF Core 不會跟蹤加載實體的變化。

關系型查詢

在 EF Core 查詢導航屬性(表關聯字段)的方式有多種:「貪婪加載」「顯式加載」「懶惰加載」

貪婪加載

貪婪加載也叫預先加載。

所謂貪婪加載,就是在查詢結果中包含導航關系,而這就需要明確的要求。

比如這個示例中,Account 擁有兩個導航屬性:

5de9908a753bc211ecd6837c8187a5f7.png

AccountDetails屬性是一對一的導航關系;

AccountSubjects屬性是一對多的導航關系。

運行這個簡單查詢的結果如下:

23cf1aa140c3fa6848dad70a3e03999d.png

可以發現,控制臺的結果中,兩個導航屬性的值都是?Null

在 EF Core 中,只有明確要求的情況下,才會在結果中包含導航關系。這個簡單查詢中,沒有明確要求包含導航關系。

如果使用貪婪加載,可以讓 EF Core 在查詢結果中包含導航屬性的值。

貪婪加載通過使用?Include()?和?ThenInclude()?方法實現,如下所示:

var?accounts?=?_context.Accounts.Include(e?=>?e.AccountSubjects).Where(s?=>?s.Age?>?16).ToList();

Include 方法用來加載第一層導航關系,如果想進一步加載導航關系呢?

比如?AccountSubjects?屬性中有兩個一對一導航,分別是?Accout?屬性和?Subject?屬性:

a56dabb1a234db19b548888405441f4c.png

如果我們想通過?AccountSubjects?導航屬性,進一步查詢出?Subject?屬性,就可以這么做 :

var?accounts?=?_context.Accounts.Include(e?=>?e.AccountSubjects).ThenInclude(s?=>?s.Subject).Where(s?=>?s.Age?>?16).ToList();

ThenInclude?方法用來進一步加載導航關系。該方法可以無限遞進非關系深度,如果關系不存在,查詢也不會失敗,只是不會返回任何東西。

「貪婪加載的優點是,以一種高效的方式,查詢了關系型數據,使用了最少的數據庫訪問次數;」

「它的缺點是,一次性加載了所有的數據,即使我們不需要其中的某些數據。」

顯式加載

所謂顯式加載,就是 EF Core 顯式地將關系,加載到已經加載的實體中。

比如這個示例:

var?account?=?_context.Accounts.FirstOrDefault();_context.Entry(account).Collection(ss?=>?ss.AccountSubjects).Load();foreach?(var?accountSubject?in?account.AccountSubjects)
{_context.Entry(accountSubject).Reference(s?=>?s.Subject).Load();
}

我們首先加載的是?Acount?實體,然后通過?AccountSubjects?導航屬性關聯所有相關的子項。

在這種情況下,Acount?實體被稱為主實體。

Collection?方法可以把一個集合納入主實體,Reference?方法可以把單一的實體納入主實體。

Account?實體通過使用?Collection?方法,包含了?AccountSubjec?集合。

AccountSubject?實體通過使用?Reference?方法,包含了?Subject?實體。

使用顯式加載時,除了?Load?加載方法,還可以使用查詢方法,它允許將查詢應用到關系中:

var?count?=?_context.Entry(account).Collection(a?=>?a.AccountSubjects).Query().Count();var?subjects?=?_context.Entry(account).Collection(a?=>?a.AccountSubjects).Query().Select(s?=>?s.Subject).ToList();

「顯式加載的好處是,只有當真正需要的時候,我們才會在實體類上加載一個導航關系。」

另一個好處是,如果我們有復雜的業務邏輯,那就可以分別加載導航關系。

另外,導航關系加載可以封裝到一個方法、甚至是一個類中,從而使代碼更容易閱讀和維護。

不過,這種方法的缺點是,會產生更多的數據庫查詢次數,來加載所有需要的關系,會降低查詢的效率。

懶惰加載

懶加載也叫延遲加載、按需加載,它和貪婪加載相反,顧名思義,暫時不需要的數據就不加載,而是推遲到使用它時再加載。

延遲加載是一個比較重要的數據訪問特性,它可以有效地減少與數據源的交互。

注意,這里所指的交互不是指交互次數,而是指交互的數據量。

EF Core 中默認是不開啟這個功能的,因為在使用不當的情況下,它會降低應用的性能。

想要使用懶加載,最簡單的辦法就是安裝?Microsoft.EntityFrameworkCore.Proxies?庫,使用代理模式實現懶加載。

在上下文類的配置方法中啟用懶加載代理:

protected?override?void?OnConfiguring(DbContextOptionsBuilder?optionsBuilder)
{optionsBuilder.UseLazyLoadingProxies();
}

配置完成后,EF Core 會為任何可以被重載的導航屬性,啟用懶惰加載。

需要注意的是,這是一種全局配置,所有的導航屬性都必須使用?virtual?修飾,否則會發生異常錯誤。

不過,這樣一來的話,所有的導航屬性都默認啟用了懶加載。

除了使用代理模式,還可以使用 EF Core 中的懶加載服務,這種方式不需要用?virtual?修飾導航屬性,而且可以只針對特定實體進行懶加載。

具體來看示例:

public?class?Account
{private?readonly?ILazyLoader?_lazyLoader;public?Account(ILazyLoader?lazyLoader){_lazyLoader?=?lazyLoader;}private?ICollection<AccountSubject>?_accountSubjects;public?ICollection<AccountSubject>?AccountSubjects{get?=>?_lazyLoader?.Load(this,?ref?_accountSubjects);set?=>?_accountSubjects?=?value;}}

使用構造函數注入的方式,將?ILazyLoader?服務注入到實體類中,然后修改需要開啟懶加載的字段。

需要注意的是,濫用懶加載,會造成性能上的問題。

雖然懶加載只在需要讀取關聯數據的時候才進行加載,但是如果在遍歷中使用的話,每次讀取一條數據,那么就會查詢一次數據庫,增加了訪問數據庫的次數,會導致數據庫的壓力增大。

貪婪加載也一樣會有性能上的問題,因為一次性讀取所有相關的數據,有可能會導致部分數據在實際上用不到,從而使查詢數據的效率降低。

所以,我們應該清楚什么時候應該使用哪種加載方式:

如果在開發時不確定是否會需要相關聯的數據,那么可以選擇懶加載,待確定需要后再加載它。

如果在開發時就可以預見,需要一次性加載所有的數據,而且需要包含導航關系的所有數據, 那么使用貪婪加載是比較好的選擇。

更多精彩內容,請關注我▼▼

20ea739fb2bbe4a1dafd07808f4c2832.gif

如果喜歡我的文章,那么

在看和轉發是對我最大的支持!

(戳下面藍字閱讀)

38f1ce930e2c942c67f5a5b709720046.png

推薦關注微信公眾號:碼俠江湖

? ? ? ? ? ? ? ? ? ? ? ??886714d5bef690057cb2ed68897e7635.png覺得不錯,點個在看再走喲

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/287657.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/287657.shtml
英文地址,請注明出處:http://en.pswp.cn/news/287657.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android Studio之導入別人的module后config.gradle配置文件沒有生效

1 問題 導入了別人項目的module,但是在別人項目里面的根目錄有config.gradle文件&#xff0c;里面有些版本信息&#xff0c;其他module的build.gradle文件用到了這里面的配置&#xff0c;如下&#xff0c;我把module導入我的項目&#xff0c;怎么讓這個文件生效呢&#xff1f;…

《零基礎看得懂的C++入門教程 》——(3)表達式花樣挺多鴨

一、學習目標 了解變量之間的計算了解什么是表達式了解什么是自增、自減 目錄 預備第一篇&#xff0c;使用軟件介紹在這一篇&#xff0c;C與C使用的軟件是一樣的&#xff0c;查看這篇即可&#xff1a;《軟件介紹》 想了解編譯原理和學習方法點這篇&#xff0c;學習方法和一些…

php 設計模式 - 單例

概述&#xff1a; 作為對象的創建模式&#xff0c;單例確保某一個內在系統中只存在一個實例&#xff0c;它不可以創建副本。 克隆函數&#xff08;__clone &#xff09;以及構造函數(__construct )必須聲明為私用&#xff0c; 防止外部程序 創建一個新類 &#xff0c;而失去…

prometheus python client

為什么80%的碼農都做不了架構師&#xff1f;>>> 當我剛開始準備使用Python寫一個promethues的client的時候&#xff0c;并沒有想到過程這么麻煩。github上的大佬們也沒興趣幫我解決這些細節的問題。以下是我在使用prometheus_client遇到的一些問題&#xff0c;僅供…

php之無限極分類

http://blog.csdn.net/kankan231/article/details/8462349/轉載于:https://www.cnblogs.com/jeremyjs/p/4798169.html

【遙感數字圖像處理】實驗:遙感影像分類(監督、非監督分類)完整流程(Erdas版)

一.實驗目的: 理解計算機圖像分類的基本原理,掌握數字圖像非監督分類以及監督分類的具體方法和過程,以及兩種分類方法的區別。 二.實驗平臺:ERDAS IMAGINE 9.1 三.實驗要求:掌握非監督分類;非監督分類結果評價;監督分類;監督分類結果評價;分類后處理。 四.實驗…

mysql5.7.16安裝版_mysql數據庫5.7.16安裝版怎么安裝圖解

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云數據庫專家保駕護航&#xff0c;為用戶…

重大跨越!Windows 11 23H2 25115 推送:2023 年更新測試開啟,水印回歸

面向 Dev 頻道的 Windows 預覽體驗成員&#xff0c;微軟現已發布 Windows 11 預覽版 Build 25115。主要變化1.微軟宣布從 Dev 頻道切換到 Beta 頻道的選項正式關閉&#xff0c;Beta 頻道將繼續測試 Windows 11 版本 22H2&#xff0c;而 Dev 頻道將開啟 2023 年更新 Windows 11 …

團隊第二次沖刺第三天

已經明白自己犯錯誤的地方&#xff0c;經過今天的改正&#xff0c;成功調用數據庫儲存用戶名和密碼。 明天對于數據庫更加完善。轉載于:https://www.cnblogs.com/dotacai/p/5521506.html

Android Studio編譯提示如下attribute layout_constraintBottom_toBottomOf (aka com.luck.pictureselector:layou

1 問題 Android Studio編譯提示錯誤如下 AAPT: error: attribute layout_constraintBottom_toBottomOf (aka com.luck.pictureselector:layout_constraintBottom_toBottomOf) not found.2 解決辦法 在app的build.gradle文件里面添加依賴如下 implementation androidx.const…

《零基礎看得懂的C++入門教程 》——(4)條件判斷原來如此

一、學習目標 了解什么是條件判斷了解多個條件判斷了解輸入了解什么是邏輯與、邏輯或 目錄 預備第一篇&#xff0c;使用軟件介紹在這一篇&#xff0c;C與C使用的軟件是一樣的&#xff0c;查看這篇即可&#xff1a;《軟件介紹》 想了解編譯原理和學習方法點這篇&#xff0c;學…

Django學習筆記(4)

為什么80%的碼農都做不了架構師&#xff1f;>>> 首先提一個問題&#xff1a;在Django中如何處理CRSF(Cross-site request forgery)? 先看一下CSRF原理。 其實就是惡意網站利用正常網站的cookie去非法請求。 ##Java處理方式## 一般做法需要后臺和前端配合采取策略去…

MySQL復制--slave設置讀取binlog的位置

change_master->global_init_info->Master_info::mi_init_info->Rpl_info_handler::init_info->Rpl_info_file::do_init_info ->mi->rli->rli_init_info()->初始化./relay-bin.000001,4如果relay-log.info不存在的話&#xff0c;否則讀取//初始化mas…

【遙感數字圖像處理】實驗:遙感專題地圖制作經典流程(Erdas版)

實驗目的:掌握計算機輔助下遙感專題地圖的制作。實驗平臺:ERDAS 9.1實驗要求:掌握專題地圖的編輯;制圖文件路徑的編輯;系列地圖編輯工具的使用。實驗步驟:1 專題地圖的編輯 1.1 準備專題制圖數據 (1) 在視窗菜單條中點擊 File,選擇Open (2) 點擊 Raster Layer,打開S…

.NET版OCR緊隨PP-OCRv3重磅發布

.net版OCR地址PaddleOCRSharp&#xff1a;https://gitee.com/raoyutian/paddle-ocrsharpPaddleOCRSharp是一個基于PaddleOCR的C代碼修改并封裝的.NET的工具類庫。包含文本識別、文本檢測、基于文本檢測結果的統計分析的表格識別功能&#xff0c;同時針對小圖識別不準的情況下&a…

mysql導出二進制日志_使用mysqlbinlog提取二進制日志

MySQL binlog日志記錄了MySQL數據庫從啟用日志以來所有對當前數據庫的變更。binlog日志屬于二進制文件&#xff0c;我們可以從binlog提取出來生成可閱讀的SQL語句來重建當前數據庫以及根據需要實現時點恢復或不完全恢復。本文主要描述了如果提取binlog日志&#xff0c;并給出相…

《零基礎看得懂的C++入門教程 》——(5) 容我套個娃 循環

一、學習目標 了解循環的使用方法 目錄 預備第一篇&#xff0c;使用軟件介紹在這一篇&#xff0c;C與C使用的軟件是一樣的&#xff0c;查看這篇即可&#xff1a;《軟件介紹》 想了解編譯原理和學習方法點這篇&#xff0c;學習方法和一些原理C與C都是相同的《脫離學習誤區》 …

Android之把app作為獨立的module導入其他項目遇到的坑

1 問題 把app作為獨立的module導入其他項目 2 步驟 1)在app的里面的build.gradle里面把 apply plugin: com.android.application 替換成如下 apply plugin: com.android.library 2)注視掉build.gradle文件里面的applicationId 3)app的AndroidManifest文件中MainActiv…

【ArcGIS風暴】ArcGIS解決數字化之前創建圖層時未定義坐標系而導致數據跑偏的問題

數字化時,第一步需要創建點線面圖層,創建圖層需要指定一個地理坐標系,但如果忽略了這一步,我們數字化的適量數據時沒有坐標系的,后果很嚴重,如果數字化工作只做了一點點,可以卷土重來;如果是大量工作的話,可以采取以下補救措施,建議收藏。 注: (1)如果底圖為無任…

Android兩個注意事項.深入了解Intent和IntentFilter(兩)

深入理解Intent和IntentFiler(二)轉載請表明出處&#xff1a;http://blog.csdn.net/u012637501(嵌入式_小J的天空) 在上一篇文章中&#xff0c;我們比較具體學習了"Intent"的相關知識&#xff0c;如今將學習怎樣設置Intent對象的這些屬性以及怎樣使用他們來啟動組件。…