Entity?Framework?Core種子數(shù)據(jù)Data-Seeding
一、什么是Data-Seeding
Data-Seeding是EntityFrameworkCore 2.1以上版本新增加的特性。在項(xiàng)目剛開始的時(shí)候,我們往往是需要初始化一些基礎(chǔ)數(shù)據(jù)到數(shù)據(jù)庫(kù)中,通過Data-Seeding特性就可以實(shí)現(xiàn)這一功能。本篇文章我們將講解如何進(jìn)行數(shù)據(jù)初始化。
二、初始化方法
具體的數(shù)據(jù)初始化方法分為如下三種:
- 模型中配置。這種是通過調(diào)用HasData()方法。
- 手動(dòng)遷移時(shí)添加。
- 自定義初始化邏輯。
下面我們分別來(lái)講解如何使用這三種方式進(jìn)行數(shù)據(jù)遷移。
1、模型中配置
這種方式是通過調(diào)用HasData()方法實(shí)現(xiàn)的。這種也是我在項(xiàng)目開發(fā)過程中,經(jīng)常使用的。這種方式是在數(shù)據(jù)上下文類中重寫OnModelCreating()方法,我們先看HasData()方法的定義:
可以看到,方法的參數(shù)可以是Blog類型的數(shù)組,具體代碼如下:
using EFCore.Model; using Microsoft.EntityFrameworkCore; namespace EFCore.Data { /// <summary> /// 數(shù)據(jù)上下文 /// </summary> public class EFDbContext:DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("Data Source=.;Initial Catalog=EFTest;User ID=sa;Password=123456;"); } public DbSet<Blog> Blogs { get; set; } /// <summary> /// 重寫OnModelCreating方法 /// </summary> /// <param name="modelBuilder"></param> protected override void OnModelCreating(ModelBuilder modelBuilder) { // 針對(duì)Blog實(shí)體添加種子數(shù)據(jù) modelBuilder.Entity<Blog>().HasData( new Blog() { // Id字段要賦值,否則會(huì)報(bào)錯(cuò) Id=1, Name="ef core" }, new Blog() { Id=2, Name="ASP.NET Core" }, new Blog() { Id=3, Name="圖解數(shù)據(jù)結(jié)構(gòu)" } ); base.OnModelCreating(modelBuilder); } } }
我們注意到:默認(rèn)情況下會(huì)自動(dòng)設(shè)置Id列為主鍵,并且是自動(dòng)增長(zhǎng)的。但是這里要設(shè)置Id的值,即使Id是自動(dòng)生成的主鍵,否則會(huì)報(bào)下圖所示的錯(cuò)誤:
添加完種子數(shù)據(jù)以后,我們運(yùn)行程序,查看輸出結(jié)果:
查看數(shù)據(jù)庫(kù):
這樣就生成了數(shù)據(jù)庫(kù)和表,而且表里面也有了初始化數(shù)據(jù)。
假如這時(shí)候我們想增加一條數(shù)據(jù),代碼如下:
using EFCore.Model; using Microsoft.EntityFrameworkCore; namespace EFCore.Data { /// <summary> /// 數(shù)據(jù)上下文 /// </summary> public class EFDbContext:DbContext { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("Data Source=.;Initial Catalog=EFTest;User ID=sa;Password=123456;"); } public DbSet<Blog> Blogs { get; set; } /// <summary> /// 重寫OnModelCreating方法 /// </summary> /// <param name="modelBuilder"></param> protected override void OnModelCreating(ModelBuilder modelBuilder) { // 針對(duì)Blog實(shí)體添加種子數(shù)據(jù) modelBuilder.Entity<Blog>().HasData( new Blog() { // Id字段要賦值,否則會(huì)報(bào)錯(cuò) Id=1, Name="ef core" }, new Blog() { Id=2, Name="ASP.NET Core" }, new Blog() { Id=3, Name="圖解數(shù)據(jù)結(jié)構(gòu)" }, // 新增加一條數(shù)據(jù) new Blog() { Id=4, Name="C#高級(jí)編程" } ); base.OnModelCreating(modelBuilder); } } }
這時(shí)候還能不能用剛才的方法呢?我們這時(shí)在運(yùn)行程序,查看結(jié)果:
這時(shí)候程序執(zhí)行失敗了,而且表里面的數(shù)據(jù)也沒有增加。這說(shuō)明context.Database.EnsureCreated()方法只有在第一次執(zhí)行的時(shí)候才會(huì)有效,以后數(shù)據(jù)進(jìn)行更改后就無(wú)效了。那么有什么方式可以實(shí)現(xiàn)呢?這時(shí)只有通過命令行進(jìn)行遷移或者通過context.Database.Migrate方法調(diào)用生成的遷移類才能對(duì)數(shù)據(jù)的更改有效。
我們把剛才生成的數(shù)據(jù)庫(kù)刪掉,新增加的那條數(shù)據(jù)注釋掉,然后使用命令行遷移的方式生成數(shù)據(jù)庫(kù)表,首先添加遷移:
然后更新數(shù)據(jù)庫(kù):
更新完數(shù)據(jù)庫(kù)以后,我們?cè)贖asData()方法里面添加一條數(shù)據(jù),然后再次執(zhí)行上面的添加遷移和更新數(shù)據(jù)庫(kù)的命令,發(fā)現(xiàn)這時(shí)候數(shù)據(jù)庫(kù)里面會(huì)添加新增加的數(shù)據(jù)。
在執(zhí)行完第二次添加遷移命令后,如果不使用更新數(shù)據(jù)庫(kù)命令,也可以通過代碼的方式進(jìn)行遷移,這就是調(diào)用context.Database.Migrate命令,代碼如下:
using EFCore.Data; using Microsoft.EntityFrameworkCore; using System; namespace EFCore.Con { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); EFDbContext dbContext = new EFDbContext(); // 遷移 dbContext.Database.Migrate(); //bool tfTrue = dbContext.Database.EnsureCreated(); //if(tfTrue) //{ // Console.WriteLine("數(shù)據(jù)庫(kù)創(chuàng)建成功!"); //} //else //{ // Console.WriteLine("數(shù)據(jù)庫(kù)創(chuàng)建失敗!"); //} Console.ReadKey(); } } }
這時(shí)會(huì)自動(dòng)調(diào)用最新的遷移文件去更新數(shù)據(jù)庫(kù)。
注意:調(diào)用該方法對(duì)數(shù)據(jù)的更改只有在遷移時(shí)才能生效,也就是說(shuō)只有通過命令進(jìn)行遷移或者通過context.Database.Migrate方法調(diào)用生成的遷移類才能對(duì)數(shù)據(jù)更改有效。而調(diào)用context.Database.EnsureCreated()方法只有在第一次執(zhí)行的時(shí)候才有效,但數(shù)據(jù)進(jìn)行更改后將無(wú)效。
這種方式有兩種限制:
- 必須指定主鍵的值(即使主鍵由數(shù)據(jù)庫(kù)自動(dòng)生成也要指定值)。
- 添加的必須是靜態(tài)數(shù)據(jù),沒有任何的依賴。比如添加的Id主鍵的值在其它表里面有引用就不可以。
2、手動(dòng)遷移時(shí)添加
這種方式在這里不進(jìn)行講解,有興趣的可以參考微軟的官方文檔。
3、自定義初始化邏輯
執(zhí)行數(shù)據(jù)種子設(shè)定的一種簡(jiǎn)單而有效的方法是在主應(yīng)用程序邏輯開始執(zhí)行之前使用使用DbContext.SaveChanges()。代碼如下:
using EFCore.Data; using EFCore.Model; using Microsoft.EntityFrameworkCore; using System; using System.Linq; namespace EFCore.Con { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); //EFDbContext dbContext = new EFDbContext(); //// 遷移 //dbContext.Database.Migrate(); ////bool tfTrue = dbContext.Database.EnsureCreated(); ////if(tfTrue) ////{ //// Console.WriteLine("數(shù)據(jù)庫(kù)創(chuàng)建成功!"); ////} ////else ////{ //// Console.WriteLine("數(shù)據(jù)庫(kù)創(chuàng)建失敗!"); ////} #region 使用自定義初始化邏輯 using(EFDbContext context=new EFDbContext()) { context.Database.EnsureCreated(); var testBlog = context.Blogs.FirstOrDefault(p => p.Name == "C#"); if(testBlog == null) { // 添加數(shù)據(jù) context.Blogs.Add(new Blog() { Name = "C#" }); } // 保存數(shù)據(jù) context.SaveChanges(); } #endregion Console.ReadKey(); } } }
通過這種自定義邏輯的方式也可以添加種子數(shù)據(jù)。如果HasData()方法里面添加了種子數(shù)據(jù),那么會(huì)先把HasData()方法里面的種子數(shù)據(jù)添加到數(shù)據(jù)庫(kù)中。如果沒有名稱為C#的數(shù)據(jù),則還會(huì)在添加一條數(shù)據(jù)。
如果有了該數(shù)據(jù),就不會(huì)再添加了。
注意:這種方式新增數(shù)據(jù)的時(shí)候就不能再給主鍵Id賦值了,因?yàn)槭窍壬蓴?shù)據(jù)庫(kù),自動(dòng)設(shè)置Id為主鍵,在添加數(shù)據(jù)的時(shí)候會(huì)自動(dòng)賦值。
三、Data-Seeding本質(zhì)
- 當(dāng)調(diào)用HasData()方法首次遷移時(shí),實(shí)質(zhì)上是調(diào)用MigrationBuilder類中InsertData方法進(jìn)行插入。
- 當(dāng)調(diào)用HasData()方法更改數(shù)據(jù)(未更改主鍵)時(shí),實(shí)質(zhì)上是調(diào)用MigrationBuilder類中UpdateData方法進(jìn)行更新操作。
- 當(dāng)調(diào)用HasData()方法移除數(shù)據(jù)或更改主鍵時(shí),實(shí)質(zhì)上是調(diào)用MigrationBuilder類中DeleteData方法進(jìn)行刪除操作或者刪除和更新操作。
1、首次遷移
我們?cè)诘谝淮螆?zhí)行完添加遷移命令以后,會(huì)生成一個(gè)遷移文件,如下圖所示:
可以看到這時(shí)就是調(diào)用的InsertData方法來(lái)新增數(shù)據(jù)。
2、修改不是主鍵的數(shù)據(jù)
我們修改數(shù)據(jù),將ef core修改為ef core 3.1.1,如下圖所示:
修改完以后我們?cè)趫?zhí)行遷移命令,如圖所示:
這時(shí)在去看生成的遷移文件:
這時(shí)執(zhí)行的就是UpdateData方法。
3、刪除數(shù)據(jù)
接著我們把Id為1的數(shù)據(jù)在代碼里面注釋掉模擬刪除操作,在執(zhí)行遷移命令:
在看生成的遷移文件:
可以看到這次就是執(zhí)行的DeleteData方法。
4、修改主鍵數(shù)據(jù)
我們?cè)诎袸d為2的數(shù)據(jù)修改為6:
在執(zhí)行遷移:
查看生成的遷移文件:
這次就是先執(zhí)行DeleteData方法,然后在執(zhí)行InsertData方法。
四、總結(jié)
針對(duì)種子數(shù)據(jù)初始化,主要有上面的三種方式,比較推薦的是第一種和第三種,可以根據(jù)自己的使用情況來(lái)選擇適合自己的。
到此這篇關(guān)于Entity Framework Core種子數(shù)據(jù)Data-Seeding的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Entity?Framework?Core生成數(shù)據(jù)庫(kù)表
- 對(duì)Entity?Framework?Core進(jìn)行單元測(cè)試
- Entity?Framework?Core相關(guān)包的概念介紹與安裝
- Entity Framework Core對(duì)Web項(xiàng)目生成數(shù)據(jù)庫(kù)表
- Entity Framework Core使用控制臺(tái)程序生成數(shù)據(jù)庫(kù)表
- Entity Framework Core延遲加載(懶加載)用法
- Entity?Framework?Core實(shí)現(xiàn)Like查詢?cè)斀?/a>
- Entity Framework Core中執(zhí)行SQL語(yǔ)句和存儲(chǔ)過程的方法介紹
- Entity Framework Core批處理SQL語(yǔ)句
相關(guān)文章
XmlReader 讀取器讀取內(nèi)存流 MemoryStream 的注意事項(xiàng)
XmlReader 讀取器讀取內(nèi)存流 MemoryStream 的注意事項(xiàng)...2007-04-04.NET中彈性和瞬時(shí)處理庫(kù)Polly的使用詳解
Polly 是一個(gè) .NET 彈性和瞬態(tài)故障處理庫(kù),允許開發(fā)人員以 Fluent 和線程安全的方式來(lái)實(shí)現(xiàn)重試、斷路、超時(shí)、隔離和回退策略,下面就跟隨小編一起來(lái)看看它的具體使用吧2024-01-01asp.net用url重寫URLReWriter實(shí)現(xiàn)任意二級(jí)域名
Asp.net 用url重寫(URLReWriter)實(shí)現(xiàn)任意二級(jí)域名2008-10-10ASP.NET(C#)實(shí)現(xiàn)一次性動(dòng)態(tài)上傳多張圖片的代碼(多個(gè)文件)
我們就要讓這些文件上傳框動(dòng)態(tài)添加,下面我以我做的一個(gè)圖庫(kù)管理中的上傳圖片的功能為例2011-10-10國(guó)產(chǎn)化之銀河麒麟安裝.netcore3.1的詳細(xì)步驟(手動(dòng)安裝)
這篇文章主要介紹了國(guó)產(chǎn)化之銀河麒麟安裝.netcore3.1的詳細(xì)步驟(手動(dòng)安裝),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03微信公眾平臺(tái)開發(fā)教程(二) 基本原理及消息接口總結(jié)
本篇文章主要介紹了微信公眾平臺(tái)開發(fā)教程(二) 基本原理及消息接口,具有一定的參考價(jià)值,有興趣的朋友可以了解一下。2016-12-12Entity?Framework?Core關(guān)聯(lián)刪除
關(guān)聯(lián)刪除通常是一個(gè)數(shù)據(jù)庫(kù)術(shù)語(yǔ),用于描述在刪除行時(shí)允許自動(dòng)觸發(fā)刪除關(guān)聯(lián)行的特征;即當(dāng)主表的數(shù)據(jù)行被刪除時(shí),自動(dòng)將關(guān)聯(lián)表中依賴的數(shù)據(jù)行進(jìn)行刪除,或者將外鍵更新為NULL或默認(rèn)值。本文將為大家具體介紹一下Entity?Framework?Core關(guān)聯(lián)刪除,需要的可以參考一下2021-12-12asp.net core集成kindeditor實(shí)現(xiàn)圖片上傳功能
這篇文章主要為大家詳細(xì)介紹了asp.net core集成kindeditor實(shí)現(xiàn)圖片上傳功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-11-11簡(jiǎn)單好用的ASP.NET分頁(yè)類(支持AJAX、自定義文字)
這篇文章主要介紹了簡(jiǎn)單好用的ASP.NET分頁(yè)類(支持AJAX、自定義文字),本文直接給出實(shí)現(xiàn)代碼和使用方法,需要的朋友可以參考下2015-06-06