2016 年 10 月

第 31 卷,第 10 期

本文章是由機器翻譯。

資料點 - 在 .NET Framework 與 .NET Core 執行 EF 核心

Julie Lerman

Julie Lerman這項技術稱為 Entity Framework 7 (EF7) 已重新命名為 Entity Framework Core (EF 核心),早期 2016。EF 核心 1.0.0 導入了一些絕佳的新功能,但整體卻有較小的功能集比 EF6。但這並不表示 EF 只會在執行.NET Core。您可以使用 EF 核心 Api,需要完整的.NET Framework 中,應用程式,以及目標只能跨平台.NET Core 中。在本專欄中,我將引導您完成探索這些選項的兩個專案。我的目標是要減輕這種 「 核心 」 moniker 可能暗示任何擔心︰ EF 核心僅.NET Core 上執行。在此同時,我將說明建立每個方案所需的步驟。

完整的.NET 專案中的 EF 核心

我一開始會以完整的.NET Framework 為目標的專案。請記住,在 Visual Studio 2015,這項工具需要您有 Visual Studio 2015 Update 3,以及最新 Microsoft ASP.NET 及 Web 工具。在撰寫本專欄 (年 8 月 2016) 時,這些安裝的最佳指南是在文件 bit.ly/2bte6Gu

為了讓我的資料存取以外的任何應用程式將會使用它,我將它自己的類別庫中建立。[圖 1 沒有特別以.NET 核心類別庫,為目標的範本,但是我要選取類別庫,一直是適用於以.NET 為目標的一般選項。產生的專案 ([圖 2) 也是 「 正常 」,您可以看到所沒有的 project.json 檔案或任何.NET Core 專案資產。一切看起來永遠有的辦法。

完整的.NET api 建立類別庫
[圖 1 完整的.NET api 建立類別庫

一般的舊 (和熟悉).NET 類別庫
[圖 2 純舊 (和熟悉).NET 類別庫

到目前為止,但這是繫結至 EF 以任何方式。我可以在此時,選擇 EF6 或 EF 核心,但我到專案中加入 EF 核心。一如往常,我可以使用 NuGet 封裝管理員來尋找並選取 EF 核心或封裝管理員主控台] 視窗。我要使用主控台。請記住,「 entityframework 」 套件的 EF6。若要取得 EF 核心,您需要安裝其中一個 Microsoft.EntityFrameworkCore 封裝。我將使用 sql Server 封裝,這會顯示在 EF 需要 sql Server 與通訊︰

install-package Microsoft.EntityFrameworkCore.SqlServer

因為該套件會取決於主要 Microsoft.EntityFrameworkCore 封裝,以及 Microsoft.EntityFrameworkCore.Relational 封裝,NuGet 會安裝對於我在相同的時間。EF 核心封裝相依於其他封裝,因為它們將會安裝,且太。在中,此程序會將三個的 EF 核心套件,以及其他 23 依賴 EF 核心的較新且更容易撰寫.net。而不是較少的大型套件,取得更多的小型封裝,但只有我的軟體需要。所有會與專案中現有的標準.NET 程式庫來播放這些。

接下來,我要加入簡單的網域類別 (Samurai.cs) 和 (SamuraiContext.cs) 可讓 EF 核心保存在資料庫中,我的資料中所示的 DbContext [圖 3。沒有 EF6 有,神奇的連接字串推斷 EF 核心,因此我必須讓它知道我使用哪個提供者和連接字串。為了簡單起見,我將著重在新的虛擬方法的 DbContext 的該權限︰ OnConfiguring。我也建立了建構函式多載,好讓我傳入的提供者和所需的其他詳細資料。我會利用這個短時間內。

[圖 3 Samurai 類別和 SamuraiContext DbContext 類別

public class Samurai
  {
    public int Id { get; set; }
    public string Name { get; set;}
  }
public class SamuraiContext : DbContext
  {
    public DbSet<Samurai> Samurais { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
      {
        if (optionsBuilder.IsConfigured == false) {
          optionsBuilder.UseSqlServer(
         @"Data Source=(localdb)\\mssqllocaldb;Initial Catalog=EFCoreFullNet;
                       Integrated Security=True;");
        }
        base.OnConfiguring(optionsBuilder);
      }
    }
    public SamuraiContext(DbContextOptions<SamuraiContext> options)
      : base(options) { }
  }

因為我使用完整的.NET 中,也表示針對完整的 Windows,我有可用的 Windows PowerShell。這表示我要使用我一律使用相同的移轉命令︰ 新增移轉、 更新資料庫等等。還有一些新命令,,,您可以看看我 2016 年 1 月的專欄 (msdn.com/magazine/mt614250),了解 EF 核心移轉命令。此外,還記得我提到封裝是較小且可撰寫嗎? 嗯,如果我想要使用 「 移轉 」,我需要加入包含這些命令的封裝。我撰寫這,這些工具會仍在預覽模式中,我需要使用-pre 參數。我要加入該封裝中,然後我可以加入新的移轉︰

install-package Microsoft.EntityFrameworkCore.Tools –pre
add-migration init

因為它永遠具有其運作原理︰ 它會建立新的移轉資料夾和移轉檔案中所示 [圖 4。EF 核心未變更其儲存模型快照集,您可以閱讀上述 2016 年 1 月資料行的方式。

我的完整.NET 類別庫中的 EF 核心移轉
[圖 4 EF 核心移轉在我的完整.NET 類別庫

就地移轉,update database 命令已成功建立新 EFCoreFullNet 資料庫為我在 SQL Server localdb。

最後,我將新增至方案的測試專案,從我在 Visual Studio 一律使用相同的單元測試專案範本。然後,我會加入我 EFCoreFullNet 類別程式庫的參考。我不需要我的測試專案,以確定 EF 核心正常運作,因此,而不是安裝 sql Server 封裝,我將會執行下列 NuGet 命令對新的測試專案中使用的資料庫︰

install-package microsoft.EntityFrameworkCore.InMemory

InMemory 提供者是針對使用 EF 核心測試壞。它使用記憶體中的資料來代表資料庫和 EF 快取,以及它會使用資料庫的相同方式互動 EF 核心非常類似的快取-新增、 移除和更新資料

還記得 SamuraiContext 中所建立的額外建構函式嗎? TestEFCoreFullNet 的測試,所示 [圖 5, ,加以利用。請注意,在測試類別的建構函式,我建立的 SamuraiContext DbContextOptions 產生器,並指定應該使用 InMemory 提供者。然後,在方法時,我將個體化 SamuraiContext,我傳入這些選項。SamuraiContext OnConfiguring 方法被設計來檢查看看是否已設定的選項。如果是的話,它會使用它們 (在此情況下,InMemory 提供者)。否則,將元件放預先設定使用 sql Server 和連接字串我硬式編碼至方法。

[圖 5 測試 EFCore

using EFCoreFullNet;
using Microsoft.EntityFrameworkCore;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
namespace Tests
{
  [TestClass]
  public class TestEFCoreFullNet
  {
    private DbContextOptions<SamuraiContext> _options;
    public TestEFCoreFullNet() {
      var optionsBuilder = new DbContextOptionsBuilder<SamuraiContext>();
      optionsBuilder.UseInMemoryDatabase();
      _options = optionsBuilder.Options;
    }
    [TestMethod]
    public void CanAddAndUpdateSomeData() {
      var samurai = new Samurai { Name = "Julie" };
      using (var context = new SamuraiContext(_options)) {
        context.Add(samurai);
        context.SaveChanges();
      }
      samurai.Name += "San";
      using (var context = new SamuraiContext(_options)) {
        context.Samurais.Update(samurai);
        context.SaveChanges();
      }
      using (var context = new SamuraiContext(_options)) {
        Assert.AreEqual("JulieSan", context.Samurais.FirstOrDefault().Name);
      }
    }
  }
}

這個測試方法採用不存在於 EF6 中某些特定 EF 核心功能。2016 年 8 月的資料點專欄中撰寫有關這些和其他 EF 核心中的變更追蹤功能 (msdn.com/magazine/mt767693)。例如,建立新的 samurai 物件之後,我加入它使用 DbContext.Add 方法,讓 EF 判斷哪些 DbSet 對它的內容必須繫結。然後我儲存的資料存放區中,在此情況下某些類型的 InMemory 提供者所管理的記憶體中的清單。接下來,我修改 samurai 物件、 建立 DbContext 的新執行個體並使用新 EF 核心更新命令,藉此確定 SaveChanges 會更新預存的 samurai 而不是建立一個新。最後,我會查詢該 samurai 內容,並使用判斷提示來確保內容確實傳回更新的名稱。

我使用的特定功能不是點,不過。重點是,我進行這項工作使用 EF 核心 「 單純舊.NET 」 中的所有 Windows 中的專案。

CoreCLR 的 EF 核心︰ 相同的程式碼,不同的相依性

我 EF 核心 Api、 相同的程式碼和相同的測試以 runtime 為目標的 CoreCLR,無法保留在 Windows 和 Visual Studio 2015 Update 3,接下來顯示如何使用相同,但看起來太類似於以 Windows 為目標。因此,我移至另一個極端而言,我說明的步驟,當我進行的 MacBook 上建立 CoreCLR 變化。

.NET core 不依賴 Windows 或它的工具。除了 Visual Studio 2015,我可以使用...嗯,我想 Emacs 舊的熱門非 Visual Studio 編輯器。不過,還有我可以選擇從 [撰寫程式碼不僅也取得功能,例如偵錯和 Git 支援某些跨平台 Ide。例如,在 2016 年 8 月號的 MSDN Magazine,Alessandro Del Sole 逐步建置 ASP.NET 核心網站使用 Visual Studio 程式碼 (msdn.com/magazine/mt767698)。我無法從他的螢幕擷取畫面,他是在 Windows 中,請參閱除此之外,體驗是基本上是相同的 mac

另一個跨平台選項是從 JetBrains 騎兵。騎兵所專用的 C# 和可描述它的最佳方式是 「 ReSharper 在它自己的 IDE 中 」。

我已經開始使用 Visual Studio 程式碼,在 Windows 與 OS X (不只是針對 C# 中,但也適用於 Node.js),而我要用來顯示目標 CoreCLR 建置的應用程式中的 EF 核心。事實上,我要建置此解決方案在 OS X,因為目標 CoreCLR 是我唯一的選項。我的媒體櫃的可用 Api 的陣列是限制較多。不過,EF 核心是相同的集合 Api 完整的.NET 程式庫中的第一個專案中我使用的時機。

如您所見,大部分的工作會在設定的專案,以及僅供以 CoreCLR 為目標的相依性。但是我可以使用相同的 SamuraiContext 類別定義我 EF 核心資料模型和相同 CanAddAndUpdateSomeData 測試方法,從先前的專案來執行相同的工作。即使我現在是限制較多的執行階段為目標,且不能使用.NET Core 以外的所有環境中運作的程式碼都是相同的。

建立程式庫類似於.NET 類別庫

我建立了包含我的程式庫和測試專案,並且針對每個專案的子資料夾的資料夾。在程式庫] 子資料夾中,我可以呼叫 dotnet 新建立的程式庫專案。[圖 6 顯示該命令,以及確認已建立專案。列出資料夾內容顯示只有兩個檔案所建立,最重要的是,project.json,其中包含必要的 NuGet 封裝和其他相關的專案詳細資料的清單。Library.cs 檔案只是空的類別檔案,我會將其刪除。

使用 dotnet 命令建立新的 CoreCLR 程式庫
[圖 6 使用 dotnet 命令建立新的 CoreCLR 程式庫

接下來,我將在 Visual Studio 程式碼中開啟這個新的程式庫專案。我可以只在提示字元中輸入 「 程式碼 」。Visual Studio 程式碼做為目標的資料夾會開啟與此、 自動辨識 json 檔案中所列的封裝,並提供執行 dotnet 還原修正無法解析相依性。好消息是,我會接受提供的。

Project.json 檔案中的程式碼看起來 [圖 7

圖 7 Project.json 檔案

{
  "version": "1.0.0-*",
  "buildOptions": {
    "debugType": "portable"
  },
  "dependencies": {},
  "frameworks": {
    "netstandard1.6": {
      "dependencies": {
        "NETStandard.Library": "1.6.0"
      }
    }
  }
}

很簡單。程式庫不需要所有 ASP.NET 核心部分用於使用,只要 NETStandard 程式庫。.NET 的標準程式庫封裝功能適用於.NET 現在可以執行的不同位置。從.NET 標準的文件 (bit.ly/2b1JoHJ),「.NET 標準程式庫是.NET Api 不會出現在所有的.NET 執行階段的正式規格 」。 因此我要建置此程式庫可以搭配.NET 的核心和 ASP.NET 核心和甚至從.NET 4.5 開始的.NET 應用程式。您可以看到相容性方格文件頁面。

我的下一個步驟是將 EF 核心加入至專案。請記住,因為我在 Mac 上,sql Server 並未提供的選項。我將使用 PostgreSQL 提供者 EF 核心相反地,這會在 project.json 的相依性目前是空的區段︰

"dependencies": {
    "Npgsql.EntityFrameworkCore.PostgreSQL": "1.0.0-*"   
  },
  "tools": {
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
  },

為之前,我打算進行移轉。一般來說,我也會將相依性加入 Microsoft.EntityFrameworkCore.Tools 包含之封裝的命令,就如同我為這個程式庫的完整.NET 版本。但 Preview 2 工具與目前的限制,因為我會延後此程序中稍後的步驟之前。不過,我需要能夠存取此程式庫資料夾中的命令,讓我新增封裝至特殊的 「 工具 」 區段的 project.json,上述程式碼所示。

在這兩個封裝,但它們的相依性,也不只會提取還原封裝。如果您檢查建立 project.lock.json 檔案中,您可以看到所有的封裝,包括 Microsoft.EntityFrameworkCore 和 Microsoft.EntityFrameworkCore.Relational—the 您所見的相同封裝加入至舊版的.NET 方案。

現在我要直接複製 Samurai.cs 和 SamuraiContext.cs 檔案中。我需要變更 OnConfiguring 類別,而不是 SQL Server 使用 PostgreSQL 和其連接字串。這是什麼該位元的程式碼現在看起來像︰

optionsBuilder.UseNpgsql(
  "User ID=julie;Password=12345;Host=localhost;Port=5432;Database=EFCoreCoreCLR;
    Pooling=true;");

它應該是執行移轉,但這裡您會遇到目前 Preview2 版本的 Visual Studio 中,外部 EFCore 工具的已知限制是,需要可執行檔的專案,才能尋找重要資產。因此,同樣地,它是有點太痛苦上第一個發生的但不是太多精力。深入了解在 bit.ly/2btm4OW

建立測試專案

我吧,我再當做可執行檔專案移轉的測試專案中加入。傳回在命令列中,移至 Oct2016DataPointsMac/測試我稍早建立的子資料夾並執行︰

dotnet new -t xunittest

在 Visual Studio 程式碼,您會看到新的測試資料夾中所列的 project.json。因為這個專案會負責確保 EF 命令列可執行,您必須將 EF 核心工具套件的參考加入至相依性。此外,測試專案需要該媒體櫃的參考,因此我也新增了,成 project.json 相依性。以下是這些新增項目後的相依性一節︰

"dependencies": {
    "System.Runtime.Serialization.Primitives": "4.1.1",
    "xunit": "2.1.0",
    "dotnet-test-xunit": "1.0.0-rc2-192208-24",
    "Library": "1.0.0",
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final"
  },

現在我可以存取的 EF 核心命令從我的文件庫資料夾。請注意,在 [圖 8 指向測試資料夾中的專案的命令使用--啟始專案參數。我要使用的每個移轉命令。

利用可執行檔的專案,以啟用使用 EF 的移轉命令的程式庫
[圖 8 利用可執行檔的專案,以啟用要使用 EF 移轉的媒體櫃的命令

從.NET 程式庫執行針對 EF 模型的移轉

請記住,我在我的專欄 EFCore 「 移轉 」 配置、 dotnet ef 的移轉命令看起來不一樣的 PowerShell 命令,但它們會導致在移轉 API 中的相同邏輯。

首先我要建立的移轉︰

dotnet ef --startup-project ../Test migrations add init

這可提供與.NET 方案相同的結果︰ 移轉與移轉快照集加入新的 Migrations 資料夾。

現在我可以建立的資料庫︰

dotnet ef --startup-project ../Test database update

我再檢查了建立 PostgreSQL 資料庫、 資料表和關聯性。有數種工具,您可以使用 OS X 中,若要這樣做。在 Mac 中,我可以使用 JetBrains 跨平台 DataGrip 為我的資料庫 IDE。

在 CoreCLR 中執行測試

最後,我 TestEFCoreFullNet 類別從舊版方案複製到我的測試] 資料夾。同樣地,我必須讓基礎結構的變更,而不是 MS 測試使用 xUnit︰ 少數的命名空間變更,移除上不當屬性、 取代事實的 TestMethod 屬性以及取代 Assert.Equal Assert.AreEqual。天啊,當然,我重新命名類別 TestEFCoreCoreClr。

Project.json 也需要知道的 InMemory 提供者,所以我加入︰

"Microsoft.EntityFrameworkCore.InMemory": "1.0.0"

[相依性] 區段,然後 「 dotnet 還原 」 尚未重新執行。

XUnit 測試專案會使用 xUnit 命令列測試執行器。因此,我回到我的終端機視窗執行命令 dotnet 測試與測試。[圖 9 顯示的輸出執行測試,成功地邁 — 除了命令列測試執行器並不提供滿足綠色傳遞測試輸出。

xUnit 傳遞測試的測試輸出
[圖 9 xUnit 傳遞測試的測試輸出

.NET 或 CoreCLR: 相同的 Api,但相同的程式碼

現在您可以看到,程式碼和相關 EF 核心的組件都相同目標將軟體設為僅在完整.NET framework 可供您使用 Windows 或 CoreCLR 上執行任何支援的環境 (Linux、 OS X、 Windows) 上是否。我無法在 Windows 電腦上完成這兩個 Visual Studio 2015 中的示範。但是我發現,將焦點放在完全無法使用完整的.NET Framework 的環境中的 CoreCLR 工作則是開眼界的方式來示範兩個地方,EF Api 和我 EF 相關的程式碼同一個。很大的差異,以及所有額外的工作,都只與目標平台 (.NET vs CoreCLR)。您可以觀賞我建立完整 ASP.NET 核心 Web API 在影片中,我 MacBook 上使用 EF 核心 1.0.0 「 看看 EF 核心 1.0 」 (bit.ly/2cmblqE)。如相同的縮寫及娛樂示範,請參閱我 DotNetFringe 工作階段的視訊 bit.ly/2ci7q0T


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

感謝下列 Microsoft 技術專家來檢閱這份文件︰ Jeff Fritz
Jeffrey T Fritz 是在處理 Web Form 和 ASP.Net 核心的 Microsoft ASP.NET 團隊的資深專案經理。跨多種縱向市場的大型與小型應用程式中的長時間 web 開發人員,他知道如何建立效能與實用性。