我是一個開發的初學者,之前也會編程,但只會寫寫Hello World和一些簡單的數據結構與算法,從來沒能夠用代碼真正做出什么東西。但是現在面臨着畢業,今年這個形勢,又不能混着混着就找到工作,所以我准備學習Asp.Net Core,現在的穩定版本是3.1,還有一個.NET5預發行版,我先學3.1。
我了解到做web應用的后端,增刪改查是核心功能,而Asp.Net Core做后端的話,EntityFramework Core是一個官方的ORM(對象關系映射),我打算先學習這種官方提供的工具,等我真正能做出東西來,又有余力的時候,再去接觸第三方的ORM。
我看過一點點視頻教程和博客,發現大佬們在做教學的時候,側重點都在EFCore的使用,而忽略了配置。大部分人都是用的Sqlite或者localdb,幾乎沒有見到真正用SqlServer來示范的。數據庫連接字符串也是常常寫到DbContext的OnConfiguring方法里或者Startup里,而不是放到appsettings.json這個配置文件里。對於我這種連數據庫連接字符串都沒寫過的純種的萌新,完全無法舉一反三,不知道該怎樣使用真正的SqlServer來配合EntityFramework Core,官方文檔也是這一嘴那一嘴,看起來不太方便。
今天總結一下簡單的使用方法以及我碰到的坑。
首先我創建了一個簡單的Web Api項目,然后添加兩個.net core類庫,現在整個解決方案就包含一個web api項目和兩個.net core類庫:
Api項目主要是Controller,Core項目是用來放實體和Dto模型等,Infrastructure打算用來放DbContext以及將來的Repositories。
添加一下引用關系,Api依賴Core和Infrastructure,Infrastructure依賴Core。
右鍵每個類庫的依賴項,點添加引用,把要添加的引用勾選上就行了。
首先我在Core下創建一個Entities文件夾,用來存放實體模型,然后在它下面創建一個Post實體模型:
然后我在Infrastructure下用Nuget包管理器先安裝EntityFramework Core:
安裝了上面三個包(聽說安裝SqlServer這個包就自動包括了EFCore這個包,我沒有嘗試),然后我在Infrastructure下創建一個Data文件夾,在里面創建一個ClamContext,繼承DbContext:
注意構造函數的寫法。因為我們想要創建一個Posts數據表,映射到我們的實體模型Post,所以用DbSet<Post>。注釋掉的是一種進階的用法,也是我踩過的坑,先不用。
然后我去Api下的appsettings.json里添加數據庫連接字符串:
連接字符串我不會寫,也是瞎抄的。Server的值要改成自己本機安裝的數據庫server名,另外我想創建一個叫Clam的數據庫,就把Database的值改成Clam。使用windows身份驗證。如果項目要部署到linux的服務器上的話,可能要進行修改。如果部署后代碼要放到Github上開源的話,可能數據庫連接字符串也不能放到appsettings.json這個配置文件里,否則就暴露自己的數據庫的Server地址了,這些都到時候再說,現在先不管。
注意,現在我並沒有在我本機的SqlServer里創建這個數據庫,我們使用EFCore來幫我們創建。
然后我們去Api下的Startup.cs類中進行配置:
這樣就配置好了,然后我們要在Api下安裝EntityFrameworkCore.Design這個包,不然會報錯。
然后就可以遷移和更新數據庫了。打開程序包管理器控制台:
首先,在控制台中把默認項目選擇成Infrastructure:
然后再下面的控制台里用Add-Migration InitialCreation指令來添加遷移,后面的InitialCreation是我給遷移起的名字,可以隨便起,但最好能看出是初始化的遷移,名字要有意義。然后再用Update-Database來更新數據庫。
如果數據庫遷移弄錯了,千萬不要直接刪掉遷移文件,最好使用Remove-Migration來刪除上一條遷移。
遷移完之后,Infrastructure里會生成一個遷移文件夾:
上面日期開頭的是遷移文件,點進去就能看到用來創建數據庫、表之類的一些代碼,讀起來跟讀英語一樣,容易理解。
下面這個模型快照我也不知道是Update以后生成的還是遷移以后就有的,我忘了看了,遷移的時候沒有bug導致我太興奮,一口氣Update了。
打開SqlServer SSMS看一下:
我們沒有在SqlServer里手動創建數據庫,Clam這個數據庫就已經自動創建好了,Posts表也建好了,三列就是我們Post實體模型里的三個屬性。ORM是對象關系映射,意思可能就是把數據庫的表映射到一個我們的對象上,每一個表就是一個實體模型的對象,表的每一列就是這個對象的每一個屬性。
下面總結一下錯誤以及解決辦法:
出現了問題先檢查一下你的EFCore的包安裝的是不是穩定版本,不要裝5.x的Preview版本。
如果添加遷移的時候出現以下錯誤:
No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext
它似乎讓我們重寫一下OnConfiguring,也就是我注釋掉的那部分,我們先不管,那是一些進階的或者高級的操作,這個方法也是來配置的。但我們已經直接在Startup里依賴注入進行配置了。
所以我猜測是你的默認啟動項目不是Api而是Infrastructure,導致Api里進行依賴注入的配置,也就是Startup里進行的配置沒能用上,所以要把Api設定成默認啟動項目。
應該把啟動項目設置成Api這個項目:
如果Api是啟動項目,依然出現這個問題,可能就是Startup里沒寫對。還有可能是DbContext里的構造函數那里出了問題,仔細檢查一下。
如果出現了這個問題:
Your startup project 'ClamHub.Api' doesn't reference Microsoft.EntityFrameworkCore.Design. This package is required for the Entity Framework Core Tools to work. Ensure your startup project is correct, install the package, and try again.
就很顯然了,去給Api裝上Design這個包就行了。
其他的問題等我遇到了再記錄。