[翻譯 EF Core in Action 1.9] 掀開EF Core的引擎蓋看看EF Core內部是如何工做的

Entity Framework Core in Action

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

第一部分目錄導航

掀開EF Core的引擎蓋看看EF Core內部是如何工做的

建立了MyFirstEfCoreApp應用程序後,你如今能夠經過它查看EF Core的工做原理,重點不在於應用程序的代碼,而是在讀取和寫入數據到數據庫時EF Core內部會發生什麼. 個人目標是讓你瞭解EF Core的工做機制,當你深刻研究本書其他部分的命令時,這會頗有幫助git

注 書中僅給出了關鍵代碼, 完整示例在 https://github.com/JonPSmith/EfCoreInAction/tree/Chapter01

數據庫建模

在對數據庫進行操做以前,EF Core必須進行數據庫建模. 數據庫建模是EF Core經過實體類和其餘EF Core配置來描述數據庫的方法. EF Core在全部的數據庫訪問中使用創建的模型github

建模在建立應用程序的DbContext時就開始了,在本例中是AppDbContext(如圖1.5所示,在上一篇文章中). 它有屬性DbSet<Book>,使得經過代碼能夠訪問數據庫數據庫

圖1.6描述了建模過程的概述,它會幫助你理解EF Core數據庫建模的過程. 後續的章節將介紹一系列配置數據庫的相關命令,在本文中使用默認配置緩存

<img src="https://img2018.cnblogs.com/blog/832799/201902/832799-20190226095156685-307163266.png" referrerpolicy="no-referrer">學習

圖1.6展現了EF Core在AppDbContext的建模步驟,下文對此過程進行更詳細的說明spa

  1. EF Core查看DbContext並找到全部公共的DbSet<T>屬性,並使用屬性名爲表定義初始名稱.
  2. EF Core查看DbSet<T>的泛型類,查看類的屬性構建列名,類型等. 它還會查找類和屬性用於提供額外建模配置的特殊Attribute
  3. EF Core查找DbSet<T>類中引用的其餘類. 在咱們的例子中Book類有一個對Author類的引用,因此EF Core也會查看它. 它對Author類執行與步驟2相同的操做. 同時它使用類名Author作爲表名
  4. 建模過程的最後一個步驟, EF Core運行DbContext的虛方法OnModelCreating, 能夠經過重寫OnModelCreating方法使用fluent Api進行更多的建模配置,但本例中爲了保持示例的簡單並無這樣作
  5. EF Core根據收集的信息建立數據庫的內部模型,並緩存數據庫模式,以便提高訪問速度. 在以後的全部的數據庫訪問中使用此模型

你可能會注意到圖1.6並無展現數據庫,由於EF Core構建內部模型時,它不會去查看數據庫. 我強調這一點是爲了說明構建一個的數據庫模型多麼重要,若是EF Core認爲數據庫模型和實際的數據庫不匹配,就會出現問題.net

在你的應用程序中你可使用EF Core來建立數據庫,這會避免出現不匹配的狀況. 若是你想要一個良好且高效的數據庫,那麼在你的代碼中編寫良好的數據庫模型是很是重要的,這樣建立的數據庫會是高效的. 建立,更新和管理數據庫結構是一個很大的主題,將在11章詳細介紹翻譯

從數據庫中讀取數據

如今能夠訪問數據庫了. 咱們使用List(l)命令,讓程序讀取數據庫並在終端上打印信息. 圖1.7顯示了輸出code

<img src="https://img2018.cnblogs.com/blog/832799/201902/832799-20190226102244267-1093071067.png" referrerpolicy="no-referrer">

下面列出代碼清單, 用於將全部的圖書與做者輸出到控制檯

<img src="https://img2018.cnblogs.com/blog/832799/201902/832799-20190226103238572-1355908645.png" referrerpolicy="no-referrer">

EF Core使用Linq(語言集成查詢)執行它想要執行的命令,使用.net類保存數據

代碼清單中粗體顯示的兩行代碼進行了數據庫訪問. 下面讓咱們看看EF Core如何使用Linq代碼訪問數據庫並返回數據. 圖1.8跟隨着這些代碼走進EF Core內部,看看鮮爲人知的故事...

<img src="https://img2018.cnblogs.com/blog/832799/201902/832799-20190226140616861-1403351889.png" referrerpolicy="no-referrer">

從數據庫中讀取數據的過程以下

  1. Linq查詢中的db.Books.AsNoTracking().Include(a => a.Author)訪問應用程序DbContext的DbSet<Book>屬性,Include(a => a.Author)顯式加載關係的Author部分. 數據庫提供程序將Linq翻譯成訪問數據庫的SQL命令. SQL被緩存以便若是再次使用相同的查詢語句時避免從新翻譯的成本 EF Core在數據庫訪問方面會盡量高效. 在這種狀況下,它將須要讀取的兩張表(Books和Author)組合到一個大表中,在一次數據庫訪問中完成工做. 下面的清單展現了EF Core和數據庫提供程序建立的SQL SELECT [b].[BookId], [b].[AuthorId], [b].[Description], [b].[PublishedOn], [b].[Title], [a].[AuthorId], [a].[Name], [a].[WebUrl] FROM [Books] AS [b] INNER JOIN [Author] AS [a] ON [b].[AuthorId] = [a].[AuthorId]
  2. 數據庫提供程序讀取數據後,EF Core經過如下過程放置數據: (a) 建立.NET類的實例 (b) 使用數據庫關係連接(外鍵),經過引用(稱爲關係修復)將.NET類連接在一塊兒. 結果是一組以正確方式連接的.NET類實例. 在本例中兩本書有相同的做者Martin Fowler,所以這兩本書的做者屬性指向同一個Author類
  3. 因爲代碼中包含 AsNoTraching, 因此EF Core知道禁止建立跟蹤快照. 跟蹤快照用於發現數據的變化, 你會在編輯WebUrl的示例中瞭解這一點. 因爲這是一個只讀查詢,所以禁用跟蹤快速會使查詢更快

更新數據庫

如今使用MyFirstEfCoreApp中的第二個命令update(u)來更新圖書Quantum Networking做者的WebUrl列. 如圖1.9所示,首先列出全部書籍,會看到最後一本書的做者沒有WebUrl. 而後運行命令u,它將要求輸入Url. 這時輸入 httqs://entangled.moon(這是一個虛構的Url,httpqs-.-),在更新成功後再次列出全部的書籍,這時能夠看到Web Url值已經更新

<img src="https://img2018.cnblogs.com/blog/832799/201902/832799-20190226132527234-735969280.png" referrerpolicy="no-referrer">

代碼清單

<img src="https://img2018.cnblogs.com/blog/832799/201902/832799-20190226133234442-1057103695.png" referrerpolicy="no-referrer">

圖1.10展現了EF Core內部發生了什麼並跟蹤其進度,這比上一個read的示例複雜許多, 所以我會給你一些提示

圖頂部的讀取階段與上一個讀取示例相似,因此應該很熟悉. 在此基礎上使用圖書的標題作爲過濾器載特定的圖書. 重要的是第2點: 對數據進行跟蹤

在圖的下半部分你能夠看到EF Core如何將加載的數據與跟蹤快照進行比較並找到更改,能夠看到只有WebUrl被更新了,它建立了一個SQL命令來只更新該列

<img src="https://img2018.cnblogs.com/blog/832799/201902/832799-20190226135002482-593136351.png" referrerpolicy="no-referrer">

圖中已經描述了大部分步驟,下面介紹Author的WebUrl列如何更新的詳細說明

  1. 應用程序使用LINQ查找包含做者信息的單個圖書,EF Core將LINQ查詢翻譯爲SQL命令,讀取Title爲Quantum Networking的行,返回Book和Author類的實例,由於使用了Single查詢,因此還會檢查是否只找到一行
  2. LINQ查詢中沒有AsNoTracking方法,因此該查詢是一個具備跟蹤的查詢,EF Core建立了數據的跟蹤快照
  3. 而後代碼更改了Book的Author的WebUrl屬性. 當調用SaveChanges時, 檢測更改階段會將跟蹤的全部類與跟蹤快照進行比較. 在這裏它會檢測到全部已更改的內容. 在本例中主鍵爲3的Author實例的WebUrl屬性值被更改
  4. 檢測到更改後,EF Core將啓動事務. 每一個數據庫更新都以原子單位完成: 更改所有成功或者所有失敗. 這很是重要,由於若是僅應用了部分更改,關係數據庫可能會發生嚴重的錯誤
  5. 更新請求由數據庫提供程序轉換爲SQL命令,若是執行成功則提交事務並返回SaveChanges方法,不然會拋出異常

原文出處:https://www.cnblogs.com/LiangSW/p/10436894.html

相關文章
相關標籤/搜索