在 .NET 6 中使用 ADO.NET 實體資料模型 — 以 Windows Form 為例

前幾天被詢問 WinForm 在 .NET 5 能否使用 Entity Framework,從微軟提供的資料來說,只要安裝 EF 6.3 以上的版本就可以運行在 .NET Core 3 與最新的.NET 5 /.NET 6 上面, 雖說是可以運行,但開發的過程中就無法使用 Visual Studio 中的 ADO.NET 實體資料模型 功能,來自動產生資料庫模型。會出現專案的目標 Framework 不包含 Entity Framework 執行階段組件。請在專案屬性頁面中,檢視目標Framework資訊。這樣的錯誤訊息。

file

變成 .NET Core 3 以上的版本,雖然可讀edmx、可讀context,但是不能幫你產模型,如果不想自己手動寫的話,微軟有提供一個範例程式,大概的意思是,在方案中開了一個 NET Core 的專案後,再加入一個 NET Framework 專案,用來使用ADO.NET 實體資料模型產 Model ,讓 NET Core 的專案參考產出後的 Model 就可以了。

雖然我沒寫過 Windows Form ,不過資料存取這方面在 .NET 是大同小異,本文的方法在 .NET Core 3、 .NET 5 與 .NET 6 都是一樣的,這邊我用 .NET 6 建立一個 WinForms 專案來示範,已經知道如何使用 ADO.NET 實體資料模型 的同學可以直接跳到在 NET 6 專案中使用 NuGet 安裝 EntityFramework小節

使用 ADO.NET 實體資料模型

並且在方案總管中,對方案按 右鍵 > 加入 > 新增專案

file

這邊我選擇建立一個.NET Framework的類別庫

file

按下一步之後,可以看到 .NET Framework 的版本是 4.7.2,最後按建立
file

建立完之後,可以看到專案中只有一個 Class.cs 檔,這個檔案我們用不到,可以直接刪除。
file

接下來就是使用 ADO.NET 實體資料模型 ,這裡對 ClassLibrary1 按右鍵 > 加入 > 新增項目。點選左邊的資料後點選ADO.NET 實體資料模型,輸入名稱後按右下角的新增

file

這裡我選來自資料庫的EF Designer,再按下一步
file

會出現選擇資料庫連線的畫面,選擇完按下一步就可以選擇 EF 的版本。
file

若沒有出現資料庫連線選項,可以按新增連接,依你的資料庫來源選擇資料來源產生相對應的連線字串,詳細內容可以跳至新增資料庫連結

選擇 Entity Framework 6.x 版本
file

依需求選擇要使用到的物件,這邊我全選資料表
file

使用T4自動產生程式碼功能時,都會跳出這類安全提示,詢問是否確定執行,這邊選確定
file

執行完成後可以看到我們的 edmx 與資料庫的資料表所對應的物件 User.cs已經在專案中
file

新增資料庫連結

選擇資料來源後按繼續
file

輸入你的資料庫伺服器名稱,並選擇登入方式後按左下角的測試連結,測試成功後就可以選擇連到我的TestDB資料庫了,完成後按確定就會回到選擇資料庫連線的畫面

file

在 .NET 6 專案中使用 NuGet 安裝 EntityFramework

一樣我們對專案按右鍵 > 管理 NuGet 套件
file

選擇 瀏覽 > 輸入搜尋關鍵字 > 選擇 EntityFramework 最新版本來安裝,這邊我安裝的最新版本是 6.4.4
file

安裝時會詢問是否同意安裝相關套件,這邊點選同意
file

並同意授權條款
file

讓 .NET 6 專案參考生成資料模型

現在讓我們修改 .NET 6 的專案檔 .csproj 檔,使之參考 ClassLibrary1 資料夾中生成的物件模型,為該 .NET 6 專案的檔案。因為 .NET Core 3 以上的版本參考edmx檔時,需要手動更改參數,這邊就無法使用 Visual Studio 的加入專案參考功能。對專案按右鍵,選擇編輯專案檔

應該會出現這樣的畫面
file

接著在<Project></Project>裡面插入以下程式碼,Compile的意思是該專案編譯時,要將Include路徑中的檔案,Link為當前專案指定路徑中的檔案,而.edmx檔需要使用EntityDeploy來進行特殊的編譯(詳細資料)。

<ItemGroup>
  <EntityDeploy Include="..\ClassLibrary1\Model1.edmx" Link="Model\Model1.edmx" />
  <Compile Include="..\ClassLibrary1\Model1.Context.cs" Link="Model\Model1.Context.cs" />
  <Compile Include="..\ClassLibrary1\Users.cs" Link="Model\User.cs" />
</ItemGroup>

file

設定完按重新建置後,應可以在方案總管中看到,物件模型已在Model資料夾中,並且檔案前面標示著捷徑箭頭圖案
file

若出現編譯錯誤

若出現以下編譯錯誤,請確定是否有用 NuGet 安裝 Entity Framework 套件
file

簡潔的參考撰寫方式

如果你有多個資料模型.cs檔,不想一個一個寫參考,這裡找到一個方法用微軟後來加入的參數就可以解決這個問題。可以用*.cs將所有.cs檔,參考至LinkBase所指定的資料夾路徑中

<Compile Include="..\ClassLibrary1\*.cs" LinkBase="Model" />

file

使用 Entity Framework 將資料庫指定資料表內容顯示在 DataGridView

先開啟 From1.cs檔 ,從左側的工具箱中,拖曳 DataGridView 物件到 Form1 畫面中,並在灰色區塊外的白色地方左鍵點擊兩下,會跳至程式碼區塊

file

接者撰寫以下程式碼,來使用 EF 連到資料庫,物件名稱為 Context.cs 中所生成的類別名稱,若跳出紅色底下,可以使用燈泡圖示來修正,引用我實際資料模型所在的 ClassLibrary1 命名空間

file

我們在Form1_Load()這個方法中將資料庫中的 Users 資料表讀取後,餵到剛剛新增的 DataGridView 的資料來源中,寫完按 F5 執行測錯,應該可以看到錯誤畫面(哈哈
file

錯誤訊息是:System.InvalidOperationException: 'No connection string named 'TestDBEntities' could be found in the application config file.'

加入資料庫連線字串

因為使用ADO.NET 實體資料模型時所建立的資料庫連線字串,儲存在我們的ClassLibary1內的App.Config檔案裡面,我們剛剛並沒有設定要參考到該檔案,我也不建議直接參考,因為裡面除了連線字串外,可能含有些我們 .NET 6 專案用不到的參數或設定。而資料庫連線字串其實會隨著你的部屬環境而變動,例如正式環境與測試環境用的是不同資料庫。所以這裡我們不直接參考ClassLibary1裡面的App.Config,而是對我們的 .NET 6 專案中,另外新增一個App.Config檔案來儲存。(你也可以偷懶複製ClassLibary1內的App.Config檔案到 .NET 6 專案內,刪除不必要的設定,只保留連線字串)

下圖是ClassLibary1內的App.Config內容
file

.NET 6 專案內的App.Config只包含連線字串的話應該如下,另外因為我們的 Model1 檔案室放在 Model 資料夾下,所以我其中的res參數路徑需要額外加上 Model資料夾名稱(資料來源)

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
        <add name="TestDBEntities" connectionString="metadata=res://*/Model.Model1.csdl|res://*/Model.Model1.ssdl|res://*/Model.Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=DANNY-LIU-ASUS;initial catalog=TestDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>

補充:若出現System.Data.Entity.Core.MetadataException: 'Unable to load the specified metadata resource.'這類錯誤訊息,請確認連線字串的參數或路徑是否有改錯
file

設定完後,按F5重新執行,在 DataGridView 中應可以正常顯示資料
file

大功告成,謝謝大家收看

延伸閱讀:
在.NET 5 / 6的 Windows Form 中使用 EF Core

Facebook留言板