今天在示範 MSBuild 如何設定 MvcBuildViews
屬性時,發現只要有 *.edmx
存在於專案中,建置的時候就會導致出現 Could not load type 'System.Data.Entity.Design.AspNet.EntityDesignerBuildProvider' 的問題,這個問題想從 Visual Studio 2019 裡面很難看出個端倪,必須改用 MSBuild 才能看出脈絡。今天這篇文章,我將分享這個問題的細部分析,並提供解決方案。
建立 MVC5 專案
為了要重現我這次遇到的問題,我們先從頭建立一個 ASP.NET MVC 5 專案,步驟如下:
-
建立 ASP.NET Web 應用程式 (.NET Framework) 專案
![建立 ASP.NET Web 應用程式 (.NET Framework) 專案](https://user-images.githubusercontent.com/88981/97080734-3f3aee00-1630-11eb-946f-be6c2f2d5d6c.png)
-
選擇 MVC 專案範本
![選擇 MVC 專案範本](https://user-images.githubusercontent.com/88981/97080737-4235de80-1630-11eb-9dd2-cb54e8f30491.png)
使用 MSBuild 建置專案
一般來說,要用命令列工具建置專案,可以用 msbuild
命令執行,以下是一些常用的命令:
-
建置 Debug 組態
msbuild /p:Configuration=Debug
-
建置 Release 組態
msbuild /p:Configuration=Release
-
建置 Release 組態 + 建置所有 Views 檢視頁面 (*.cshtml
)
msbuild /p:Configuration=Release /p:MvcBuildViews=true
如果想知道如何在 Visual Studio 裡面設定 MvcBuildViews
建置的話,可以參考我這篇文章:ASP.NET MVC 開發心得分享 (11):對 Views 進行編譯檢查
當你啟用了 MvcBuildViews
目標,MSBuild 會幫你用 aspnet_compiler.exe
( 位於 C:\Windows\Microsoft.NET\Framework\v4.0.30319
目錄 ) 來建置整個專案目錄,建置過程的畫面如下:
![msbuild /p:Configuration=Release /p:MvcBuildViews=true](https://user-images.githubusercontent.com/88981/97080995-07cd4100-1632-11eb-8655-d51dcdb47533.png)
使用 Visual Studio 加入 ADO.NET 實體資料模型 (ADO.NET Entity Data Model)
-
新增項目
![新增項目 - ADO.NET 實體資料模型](https://user-images.githubusercontent.com/88981/97081164-136d3780-1633-11eb-88d1-ce2f3cc9ca7f.png)
-
實體資料模型精靈 / 選擇模型內容 / 來自資料庫的 EF Designer
![實體資料模型精靈 / 選擇模型內容 / 來自資料庫的 EF Designer](https://user-images.githubusercontent.com/88981/97081209-61823b00-1633-11eb-9400-4b50fabe3adf.png)
-
實體資料模型精靈 / 選擇您的資料連結 / 您的應用程式應使用哪個資料連接來連接到資料庫?
![實體資料模型精靈 / 選擇您的資料連結 / 您的應用程式應使用哪個資料連接來連接到資料庫?](https://user-images.githubusercontent.com/88981/97081243-9ee6c880-1633-11eb-867f-0b1f1407d412.png)
-
實體資料模型精靈 / 選擇您的版本 / 您要使用哪一個 Entity Framework 版本? / Entity Framework 6.x
![實體資料模型精靈 / 選擇您的版本 / 您要使用哪一個 Entity Framework 版本?](https://user-images.githubusercontent.com/88981/97081272-dbb2bf80-1633-11eb-9199-e1325df7baef.png)
-
實體資料模型精靈 / 選擇您的資料庫物件和設定 / 您的模型中要包含哪些資料庫物件?
![實體資料模型精靈 / 選擇您的資料庫物件和設定 / 您的模型中要包含哪些資料庫物件?](https://user-images.githubusercontent.com/88981/97081293-0bfa5e00-1634-11eb-9f2a-675a4359b91e.png)
按下完成後,將會建立一個 ContosoUniversity.edmx
實體資料模型(EDM)檔案!
-
建置專案 (F6) (Ctrl-Shift-B)
確認建置成功!
重現 MvcBuildViews
無法建置專案的問題
-
建置 Release 組態 + 建置所有 Views 檢視頁面 (*.cshtml
)
msbuild /p:Configuration=Release /p:MvcBuildViews=true
-
此時你就可以開始看見建置失敗的錯誤了!
MvcBuildViews:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe -v temp -p G:\Projects\MVC5EF6Demo\MVC5EF6Demo
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config(115): error ASPCONFIG: Could not load type 'System.Data
.Entity.Design.AspNet.EntityDesignerBuildProvider'. [G:\Projects\MVC5EF6Demo\MVC5EF6Demo\MVC5EF6Demo.csproj]
![C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config(115): error ASPCONFIG: Could not load type 'System.Data.Entity.Design.AspNet.EntityDesignerBuildProvider'.](https://user-images.githubusercontent.com/88981/97081401-d6a24000-1634-11eb-8e00-3c32046b2432.png)
-
分析發生問題原因
這個錯誤來自於 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config
檔案的第 115 行,這行的原始碼如下:
<add extension=".edmx" type="System.Data.Entity.Design.AspNet.EntityDesignerBuildProvider"/>
注意:這個 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config
檔案為整台主機所有 ASP.NET 應用程式預設載入的 web.config
設定檔,這意味著每一個執行在這台主機的 ASP.NET 網站,都是先載入這個「全域設定檔」然後才載入網站本身的 web.config
檔!
這段設定位於 <compilation>
/ <buildProviders>
區段內,這意味著所有 .edmx
預設都會採用 System.Data.Entity.Design.AspNet.EntityDesignerBuildProvider 進行建置,並動態產生必要的原始碼 (CSDL, SSDL,MSL)。
這段錯誤訊息顯示 Could not load type 'System.Data.Entity.Design.AspNet.EntityDesignerBuildProvider' 的意思,很明顯是有「組件」(Assembly) 沒有被載入才導致這個問題發生!
解決方案
只要從專案根目錄的 web.config
額外載入 System.Data.Entity.Design
組件,這個問題就可以完美解決!
你只要在專案根目錄的 web.config
找到 <system.web>
/ <compilation>
區段,並加入 System.Data.Entity.Design
組件,就可以讓 ASP.NET 找到 System.Data.Entity.Design.AspNet.EntityDesignerBuildProvider
這個型別:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.7.2">
<assemblies>
<add assembly="System.Data.Entity.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</assemblies>
</compilation>
</system.web>
</configuration>
其實這段設定應該被放進 C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\web.config
檔案才對,你可以試試將上述設定加入到該檔案中,也能完美解決此問題。不過,如果每位開發人員的電腦都要做這樣的設定,似乎不太明智,還是放在專案的 web.config
之中並加入版控比較一勞永逸。
從 這篇 StackOverflow 的貼文看來,這個問題已經超過 10 年都沒有解決。我自己主觀臆測可能是因為 System.Data.Entity.Design
屬於「開發時期」才會用到的組件,若是放進全域的 web.config
設定中,感覺會載入額外的組件,增加記憶體耗用,所以才預設移除,因此讓有需要的專案自行加入才能使用,也算是個合理的解釋。可惜官方文件完全沒提到這個設定,且也只有需要建置 Views 檔案的時候才用的到,因此第一時間比較難找到解決方案!
相關連結