Entity Framework Core 2.1,新增種子資料

solenovex發表於2018-10-29

EFCore 2.1出來有一段時間了,裡面的新功能還沒怎麼用,今天研究下如何使用EF Core 2.1新增種子資料。

這部分的官方文件地址是:https://docs.microsoft.com/en-us/ef/core/modeling/data-seeding

我們在開發時總是需要新增一些種子資料的,所以這個功能還是比較有用的。

 

準備工作

我建立了一個ASP.NET Core專案,裡面有幾個Model,其中一個是省份Province,另一個是城市City:

 

裡面還涉及到其它的Model,不過本文用不到,就不貼了。

 

該專案使用的資料庫是MSSQL LocalDB。並已經做好了上述Models的遷移工作。

該資料庫裡面存在過一些資料,但是現在都被我刪除了。

 

新增第一個種子資料

直接在DBContext的OnModelCreating方法裡使用HasData()方法:

這裡我新增了一個省份的種子資料,並寫上了主鍵Id的值

資料庫該表的主鍵Id是int自增的。Id為1的資料曾經存在過,但是被我刪除了。

然後看看會發生什麼

 

生成的遷移類

命令:Add-Migration Xxx

看一下生成的遷移類的內容:

 

生成的SQL指令碼

命令:Script-Migration

這是裡面關於插入資料的部分:

 

 遷移到資料庫

命令:Update-Database -Verbose

結果是成功的。

看紅線那兩句話,EFCore在執行的過程中臨時更改了設定,可以插入主鍵的值,然後又禁用了插入主鍵。

 

資料庫裡面的資料

雖然曾經存在過Id為1的資料(然後被刪除了),但是Id為1的種子資料仍然可以插入進去。

 

種子資料的主鍵必須有值

我再新增一個沒有主鍵Id值的種子資料:

 

然後Add-Migration,看看會發生什麼:

報錯了,所以主鍵值是必填的。

 

當我填寫了主鍵值之後,一切都是好用的了:

 

更改現有的種子資料

我在HasData方法裡更改了現有的種子資料,但是主鍵的值並沒有改:

執行Update-Database時的SQL語句:

可以看到是根據主鍵對資料庫裡面的資料進行Update動作。

 

其結果也和我想的一樣,就是更新了現有的資料:

 

如果我把HasData裡種子資料的主鍵值修改了

我把四川的主鍵從2改為3。

 

看下生成的遷移檔案:

先刪除了之前新增的Id為2的種子資料,然後把插入了一筆Id為3的資料。

 

看下SQL:

也是先Delete,再Insert。

 

資料庫裡:

 

種子資料為什麼要指定主鍵的值?

 因為在團隊開發時,這樣可以確保不同的開發人員、電腦、伺服器上,在同一個遷移版本具有相同的種子資料

 

新增關聯種子資料

Province和City是一對多的關係,也就是說一個Province可以有多個City,而且它們之間有導航屬性。

下面看看一次性新增Province和City是否可以行,我直接在HasData方法裡這樣寫:

 

然後Add-Migration

這樣做不行。我必須單獨新增City的種子資料,並且設定好外來鍵

 

所以正確的做法是:

這次Add-Migration沒有報錯,遷移也成功了,看一下最後的資料:

OK

 

如果無法在Model裡設定主鍵/外來鍵

有時,我們在主從關係的Model裡不明確定義外來鍵;有時候我們Model的主鍵是private set的;

這時我們就無法在HasData裡設定主鍵/外來鍵的值了,那麼如何來新增種子資料呢?

答案就是使用匿名類

 

我把City Model裡的外來鍵去掉(導航屬性仍然保留,和Province的主從關係依然存在):

 

然後就可以這樣新增種子資料:

 

遷移後的資料:

結果仍然如預期一樣。

 

如果主鍵是Guid型別呢?

看下資料:

貌似沒問題。

 

如果我不修改這個種子資料,再執行一次遷移呢?

看一下這時的遷移檔案:

刪除原來的資料,再插入一個新的資料。。

資料庫裡也是這樣的:

 

所以最好的辦法是把Guid的值放在一個變數裡

然後再操作一遍:

這樣就不會出現“把原有資料刪掉,再重新插入”這種操作了。

 

其它

使用context.Database.EnsureCreated()會建立一個新的資料庫,幷包含有種子資料。但是如果資料庫已經存在了,那麼EnsureCreated()不會更新資料庫,也不會新增種子資料了。

 

相關文章