2017 年 1 月

第 32 卷,第 1 期

本文章是由機器翻譯。

資料點 - EF Core 1.1: 我最喜歡的兩三事

Julie Lerman

Julie Lerman我撰寫此資料行 (在 11 月 2016),Entity Framework (EF) 核心 1.1 才剛發行。1.0 版和 1.1 版,之間發生的一些重要事項。特別是,1.0.1 修補程式修正 1.0 發行時一樣,發現一些重要的問題。如需這些修正程式的詳細清單,您可以閱讀的版本資訊bit.ly/2fl5xNE。雖然這些修正程式大都如何將 LINQ 查詢轉換成 SQL,還有模型產生器,透過 SaveChanges 和移轉作業的持續性的修正程式。

EF 核心 1.1 顯示其他錯誤修正、 LINQ 查詢的解譯方式,許多其他增進功能和效能提升。但也有新功能 — 部分在於 EF6,但還沒對 EF 核心 1.0 時,讓許多開發人員甚至查看 EF 核心 — 及其他完全陌生。我想要在這篇文章會提供簡要的這些變更,然後反白我覺得很有趣的部分。我也會提供許多我使用我的工作跟 EF 核心發展出來的寶貴資源的連結。一開始,文件中涵蓋這項資訊大量 (docs.microsoft.com/ef) 和小組部落格文章中 (bit.ly/2ehZBUB)。

特別是,您應該注意的推理作家科南 Vickers 部落格。科南是資深的開發人員已經小組的 POCO 起始 ef 支援且已被 EF 現代化很有幫助。他有一系列好用的文章在 EF 核心 1.1 blog.oneunicorn.com

Microsoft 計劃許多 EF6 功能帶入 EF 核心,但並非全部。而且有許多新功能計劃,將在未來版本中介紹。現在,以滑鼠右鍵 EF 核心 1.1 重點放在升級時,會對 EF 核心更令人滿意的更多的開發。以下是最重要的這些功能。

現在在 EF 1.1 EF6 功能

DbSet.Find 方法,這項建議適用於在 EF 4.1 DbContext API 的簡介,不讓 EF 核心的第一個反覆項目叫用清單 upsetting 許多開發人員。尋找多個方便的方式有效率地查詢實體根據其索引鍵值。它會先檢查,查看該實體已經在記憶體中並正在追蹤 EF。如果 DbContext 快取中找不到實體,EF 將可擷取的實體資料庫上執行 FirstOrDefault 查詢。這用來在 EF6 或更早版本的 SingleOrDefault 查詢。若要避免不必要來回存取資料庫尋找設計也是提升效能。如果您像我一樣,而且想要查看配管,您可以在 GitHub 上 EntityFinder 類別中找到的程式碼 (bit.ly/2e9V0Uu)。

其他主要的差別在於尋找目前處於 EntityFinder 服務;不只是就跟 EF6,直接在內部的 DbSet 類別中實作的方法。EF 核心組成數百個服務,將特定工作的封裝。他在 EF 核心 1.1 Channel 9 影片示範 (bit.ly/2fHOCsN),Rowan Miller 將示範如何直接使用服務的方式,來取代它們。

也變得 1.1 update EF 核心部分是 EF6 功能稱為連接恢復功能,可輕鬆地處理暫時性連接問題可能會發生使用對遠端資料庫,例如 Azure SQL Database 時提供支援。SQL 資料庫提供者的 EnableRetryOnFailure 延伸方法可以設定 DbContext.OnConfiguring 或 Startup.cs 的 AddDbcontext 呼叫中,如果您使用 ASP.NET 的核心相依性插入。EnableRetryOnFailure 呼叫 SqlServerRetryingExecutionStrategy,繼承自 ExecutionStrategy 輸入。您可以建立並設定您自己的 ExcecutionStrategy 和其他提供者可以預先自己 ExecutionStrategy 組態,以及定義。如果您不熟悉這項功能,就像是 EF6 DbExecutionStrategy,這我進一步探討在我 Pluralsight 課程中,「 EF6 忍者版 」 (bit.ly/PS_EF6)。

EF 一直都提供三種方式載入相關的資料。其中一個,積極式載入時,會啟用 DbSet.Include 方法來擷取單一查詢中資料的圖形。其他兩個,相較之下,載入相關的資料後的主要物件已在記憶體中並正在追蹤的 DbContext 時仍在範圍內。消極式載入會自動包含過度使用相關的資料視時使用明確載入您明確告知 EF 來載入相關的資料。包含第一個在 EF 核心中實作,會變成可用 EF 核心 1.0。它甚至還有一些不錯的功能改良,透過從 EF6 或更早版本的版本。明確載入的 Load 方法現在已加入至 EF 核心 1.1。尚未支援消極式載入,但會在某個時間點。

DbContext 的變更追蹤 Api 可讓您存取直接變更追蹤程式資訊,例如取得或設定與 DbContext.Entry(someObject) 實體的狀態。狀態的方法。EF6 隨行 GetDatabaseValues、 CurrentValues 和 OriginalValues 之類的新方法,其他的控制項。這些方法現在已提供 EF 核心 1.1。

EF 1.1 中的新功能

EF 核心會填入從未存在於較早版本的功能。以下是簡短清單的範例︰ 批次處理 SaveChanges、 唯一的外部索引鍵、 很棒的 InMemory 提供者期間進行測試,更聰明的 LINQ 查詢處理,並更聰明及更簡單的 fluent 對應。

EF 1.1 帶來一些其他新功能,而且有一個特別是,為人是誰熱衷的 Domain-Driven 設計 (DDD),我很喜歡 — 支援封裝的集合。

對應欄位和封裝集合EF Code First 僅支援對應至屬性 getter 和 setter,即使 set 存取子是私用。為集合導覽屬性所必須是 ICollection。如果您想要限制屬性的值填入的方式,來封裝屬性的能力很重要,如此一來您可以強制使用公用的方法,以確保該屬性的商業規則並接受使用這個類別的任何人。EF6 和稍早可讓您藉由 setter 私用封裝純量屬性。但是沒有辦法真正封裝集合,並防止他人直接修改集合。

使用 EF 1.1 中,您就可以直接對應到欄位,以及對應至 IEnumerable 屬性。對應至欄位,不只是屬性,可讓您使用更直接的方法而不是隱藏 setter 和它也支援一些其他的方法封裝純量值的新功能。以下是 DueDate _dueDate,繫結至屬性欄位,以及具有 getter,但沒有 set 存取子,屬性︰

private DateTime _dueDate;
public DateTime DueDate {
  get { return _dueDate;
  }
}

設定 DueDate 的唯一方式是藉由呼叫 CalculateDueDate 方法,修改欄位︰

private void CalculateDueDate() {
  _dueDate=Start.AddDays(DaysLoaned);
}

EF 核心 1.1 需要明確的對應,以通知它可以使用 _dueDate 欄位對應至資料庫,例如,在傳回查詢結果的 EF DbContext 中。您必須使用屬性 (並選擇性地 HasField) API 方法,以指定 _dueDate 欄位是 DueDate 屬性的替代品。在此情況下,因為欄位名稱,而 _dueDate,遵循 EF 慣例,不必使用 HasField 方法,但我新增了在因此您可以看到它︰

protected override void OnModelCreating(ModelBuilder modelBuilder) {
  modelBuilder.Entity<BookLoan>().Property(bl => bl.DueDate)
  .HasField(“_dueDate”);
}

雖然可用的欄位對應之前,您可以使用私人 setter,沒有方法來封裝集合,以防止任何人都直接管理透過新增或移除方法集合。它不是關乎隱藏 setter。需要的是隱藏的集合的方法。DDD 中的常見方法是將屬性設為 IEnumerable。不過,使用 EF6 和更早版本,您只能對應到 ICollection; 的類別不是 IEnumerable ICollection。

一開始我討論請參閱 < 如果您可以使用的欄位對應功能,但不可能的因為它只支援純量屬性對應的 EF 1.1。這被目標 EF 核心,可讓對應至導覽屬性的下一個版本中變更。但我特別提出這一天在 Twitter 上,當推理作家科南 Vickers 讓我知道,實際上您可以對應至 IEnumerables — 我稍微遺漏了解 EF 核心內容。所以我現在可以封裝和保護集合完全,強迫我 api 來瀏覽一種方法來修改集合的使用者。以下是的範例,我可以新增新的 BookLoan 執行個體到活頁簿每次它是借貸,確保在這段貸款是否包含︰

private List<BookLoan> _bookLoans;
public IEnumerable<BookLoan> BookLoans {
  get { return _bookLoans; }
}
public void BookWasLoaned(int daysLoaned){
  _bookLoans.Add(new BookLoan(DateTime.Today, 14));
}

這是一種利用 IEnumerable 對應達成封裝的模式。但我建議您閱讀 Arthur 的部落格文章 (bit.ly/2fVzIfN) 如需詳細資訊,包括如何執行此動作不支援欄位 (a la 我 _bookLoans 欄位),計劃的增強功能和一些問題需要注意。

對特定資料庫功能的支援EF 核心的設計可讓提供者可以更輕鬆地支援特定功能的資料存放區。其中一個範例是針對 EF 核心的 SQL Server 提供者所支援的應用程式 SQL Server Memory-Optimized 資料表具有非常高的輸送量。若要指定實體對應到這種特殊資料表,SQL Server 提供者已設定您的模型,使用 Fluent API 時,您可以使用擴充方法︰

modelBuilder.Entity<Book>().ForSqlServerIsMemoryOptimized();

不只將此程式碼第一次產生的影響資料表建立指令碼,但它也會影響 EF 如何產生推播資料到資料庫的命令。您可以看到有趣的示範,這在先前所述的 Channel 9 影片 Rowan Miller 示範 EF 1.1 功能的位置。

Shay Rojansky 建造 EF 核心的 PostgreSQL 提供者,寫過一篇關於 EF 核心如何讓他可以支援的 PosgreSQL 的特殊功能,例如陣列型別。在讀取bit.ly/2focZKQ

更容易存取服務

如我前面強調 EntityFinder 服務,EF 核心組成數百個服務。在 Channel 9 影片中,Rowan 會示範如何存取並直接在您的程式碼中使用這些服務。此外,您可以使用您自己的自訂覆寫服務。EF 1.1 輕鬆執行簡單取代可以用於 OnConfiguring 的方法。您可以使用該服務會繼承或實作相同介面的另一個取代服務。沒有特定的服務清單,這些是整個各種 Api 的 EntityFrameworkCore 只是類別。簡單-掌握範例會建立繼承自資料庫型別對應程式,例如 SqlLiteTypeMapper Sqlite 者的類別,並新增新的型別對應規則。請確定該規則是其中一個資料庫,是能夠轉換。(EF 核心的未來版本將即將一些 cleverer 的型別轉換)。 然後,在 OnConfiguring,設定取代規則︰

optionsBuilder.ReplaceService<SqliteTypeMapper,MySqliteTypeMapper>();

為什麼我無法取代 EntityFinder 服務? 首先,因為我喜歡它的運作方式。但第二,因為它是泛型類別,可讓您建立的新版本比較複雜,設定目前的磁碟空間的簡潔,我選擇。ReplaceService 已建立時,方便您更輕鬆地將內部服務,您需要謹記在心,都可以變更 EF 核心內部,而且您取代因此,可能造成進一步問題。您可以識別這些容易因為它們在命名空間,以供內部使用這個字結尾。Microsoft: 「 我們通常避免在非重大變更。在次要的內部命名空間和修補程式版本。 」

值得注意 (因為它會導致一些希望挑起這方面當時) 是與使用發現如同 1.0 所要釋放的 Include 方法的非同步查詢相關的效能問題的修正程式。它快速解決 (請參閱bit.ly/2faItD1如果您想要在詳細資料),而且報告的 70%增加效能,同時也在 1.1 版。

總結

EF 核心有很多複雜的功能。它是非常重要,要注意的內容、 什麼不是、 未來和什麼絕不要將 EF 核心的一部分。關於 EF6 其關聯的 EF 核心文件 (bit.ly/2fxbVVj) 是相當實用的資源,以及。重點是,您決定何時 EF 核心是對您和您的應用程式。

大部分的執行的工作,EF 核心 1.1 有 Api 和我所需的功能。DDD 從業,封裝集合的能力是贏家對我而言,但我仍在等待,我也可以使用值的物件,在我的模型中要包含的複雜型別對應。這項功能被預定 EF 核心的下一個版本。我也很興奮地最近發現 EF 核心已完成我想,來定義唯讀的 (非追蹤) DbContext。我完全遺漏了這早期加入,而且是 1.0 版的 EF 核心的一部分。您可以深入了解,在我的部落格文章, bit.ly/2f75l8m


Julie Lerman是 Microsoft MVP,.NET 指導和居住在佛蒙特山區的顧問。 您可以找到其資料存取與其他.NET 主題,在使用者群組和世界各地的研討會上呈現。她的部落格網址thedatafarm.com /blog以及 Code First DbContext 版本中的,所有從 O'Reilly Media 是 「 程式設計 Entity framework 」。在 Twitter 上追隨她︰ @julielerman ,請參閱在她 Pluralsight 課程juliel.me/PS 影片

感謝下列 Microsoft 技術專家來檢閱這份文件︰ Rowan Miller


討論 MSDN Magazine 論壇的文章