Entity?Framework?Core種子數(shù)據(jù)Data-Seeding
一、什么是Data-Seeding
Data-Seeding是EntityFrameworkCore 2.1以上版本新增加的特性。在項目剛開始的時候,我們往往是需要初始化一些基礎(chǔ)數(shù)據(jù)到數(shù)據(jù)庫中,通過Data-Seeding特性就可以實現(xiàn)這一功能。本篇文章我們將講解如何進行數(shù)據(jù)初始化。
二、初始化方法
具體的數(shù)據(jù)初始化方法分為如下三種:
- 模型中配置。這種是通過調(diào)用HasData()方法。
- 手動遷移時添加。
- 自定義初始化邏輯。
下面我們分別來講解如何使用這三種方式進行數(shù)據(jù)遷移。
1、模型中配置
這種方式是通過調(diào)用HasData()方法實現(xiàn)的。這種也是我在項目開發(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)
{
// 針對Blog實體添加種子數(shù)據(jù)
modelBuilder.Entity<Blog>().HasData(
new Blog()
{
// Id字段要賦值,否則會報錯
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);
}
}
}我們注意到:默認情況下會自動設(shè)置Id列為主鍵,并且是自動增長的。但是這里要設(shè)置Id的值,即使Id是自動生成的主鍵,否則會報下圖所示的錯誤:

添加完種子數(shù)據(jù)以后,我們運行程序,查看輸出結(jié)果:

查看數(shù)據(jù)庫:

這樣就生成了數(shù)據(jù)庫和表,而且表里面也有了初始化數(shù)據(jù)。
假如這時候我們想增加一條數(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)
{
// 針對Blog實體添加種子數(shù)據(jù)
modelBuilder.Entity<Blog>().HasData(
new Blog()
{
// Id字段要賦值,否則會報錯
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#高級編程"
}
);
base.OnModelCreating(modelBuilder);
}
}
}這時候還能不能用剛才的方法呢?我們這時在運行程序,查看結(jié)果:

這時候程序執(zhí)行失敗了,而且表里面的數(shù)據(jù)也沒有增加。這說明context.Database.EnsureCreated()方法只有在第一次執(zhí)行的時候才會有效,以后數(shù)據(jù)進行更改后就無效了。那么有什么方式可以實現(xiàn)呢?這時只有通過命令行進行遷移或者通過context.Database.Migrate方法調(diào)用生成的遷移類才能對數(shù)據(jù)的更改有效。
我們把剛才生成的數(shù)據(jù)庫刪掉,新增加的那條數(shù)據(jù)注釋掉,然后使用命令行遷移的方式生成數(shù)據(jù)庫表,首先添加遷移:

然后更新數(shù)據(jù)庫:

更新完數(shù)據(jù)庫以后,我們在HasData()方法里面添加一條數(shù)據(jù),然后再次執(zhí)行上面的添加遷移和更新數(shù)據(jù)庫的命令,發(fā)現(xiàn)這時候數(shù)據(jù)庫里面會添加新增加的數(shù)據(jù)。
在執(zhí)行完第二次添加遷移命令后,如果不使用更新數(shù)據(jù)庫命令,也可以通過代碼的方式進行遷移,這就是調(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ù)庫創(chuàng)建成功!");
//}
//else
//{
// Console.WriteLine("數(shù)據(jù)庫創(chuàng)建失敗!");
//}
Console.ReadKey();
}
}
}這時會自動調(diào)用最新的遷移文件去更新數(shù)據(jù)庫。
注意:調(diào)用該方法對數(shù)據(jù)的更改只有在遷移時才能生效,也就是說只有通過命令進行遷移或者通過context.Database.Migrate方法調(diào)用生成的遷移類才能對數(shù)據(jù)更改有效。而調(diào)用context.Database.EnsureCreated()方法只有在第一次執(zhí)行的時候才有效,但數(shù)據(jù)進行更改后將無效。
這種方式有兩種限制:
- 必須指定主鍵的值(即使主鍵由數(shù)據(jù)庫自動生成也要指定值)。
- 添加的必須是靜態(tài)數(shù)據(jù),沒有任何的依賴。比如添加的Id主鍵的值在其它表里面有引用就不可以。
2、手動遷移時添加
這種方式在這里不進行講解,有興趣的可以參考微軟的官方文檔。
3、自定義初始化邏輯
執(zhí)行數(shù)據(jù)種子設(shè)定的一種簡單而有效的方法是在主應(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ù)庫創(chuàng)建成功!");
////}
////else
////{
//// Console.WriteLine("數(shù)據(jù)庫創(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ù),那么會先把HasData()方法里面的種子數(shù)據(jù)添加到數(shù)據(jù)庫中。如果沒有名稱為C#的數(shù)據(jù),則還會在添加一條數(shù)據(jù)。
如果有了該數(shù)據(jù),就不會再添加了。
注意:這種方式新增數(shù)據(jù)的時候就不能再給主鍵Id賦值了,因為是先生成數(shù)據(jù)庫,自動設(shè)置Id為主鍵,在添加數(shù)據(jù)的時候會自動賦值。
三、Data-Seeding本質(zhì)
- 當調(diào)用HasData()方法首次遷移時,實質(zhì)上是調(diào)用MigrationBuilder類中InsertData方法進行插入。
- 當調(diào)用HasData()方法更改數(shù)據(jù)(未更改主鍵)時,實質(zhì)上是調(diào)用MigrationBuilder類中UpdateData方法進行更新操作。
- 當調(diào)用HasData()方法移除數(shù)據(jù)或更改主鍵時,實質(zhì)上是調(diào)用MigrationBuilder類中DeleteData方法進行刪除操作或者刪除和更新操作。
1、首次遷移
我們在第一次執(zhí)行完添加遷移命令以后,會生成一個遷移文件,如下圖所示:

可以看到這時就是調(diào)用的InsertData方法來新增數(shù)據(jù)。
2、修改不是主鍵的數(shù)據(jù)
我們修改數(shù)據(jù),將ef core修改為ef core 3.1.1,如下圖所示:

修改完以后我們在執(zhí)行遷移命令,如圖所示:

這時在去看生成的遷移文件:

這時執(zhí)行的就是UpdateData方法。
3、刪除數(shù)據(jù)
接著我們把Id為1的數(shù)據(jù)在代碼里面注釋掉模擬刪除操作,在執(zhí)行遷移命令:
在看生成的遷移文件:

可以看到這次就是執(zhí)行的DeleteData方法。
4、修改主鍵數(shù)據(jù)
我們在把Id為2的數(shù)據(jù)修改為6:

在執(zhí)行遷移:

查看生成的遷移文件:

這次就是先執(zhí)行DeleteData方法,然后在執(zhí)行InsertData方法。
四、總結(jié)
針對種子數(shù)據(jù)初始化,主要有上面的三種方式,比較推薦的是第一種和第三種,可以根據(jù)自己的使用情況來選擇適合自己的。
到此這篇關(guān)于Entity Framework Core種子數(shù)據(jù)Data-Seeding的文章就介紹到這了。希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Entity?Framework?Core生成數(shù)據(jù)庫表
- 對Entity?Framework?Core進行單元測試
- Entity?Framework?Core相關(guān)包的概念介紹與安裝
- Entity Framework Core對Web項目生成數(shù)據(jù)庫表
- Entity Framework Core使用控制臺程序生成數(shù)據(jù)庫表
- Entity Framework Core延遲加載(懶加載)用法
- Entity?Framework?Core實現(xiàn)Like查詢詳解
- Entity Framework Core中執(zhí)行SQL語句和存儲過程的方法介紹
- Entity Framework Core批處理SQL語句
相關(guān)文章
asp.net頁面觸發(fā)事件panel滾動條高度不變的實現(xiàn)方法
asp.net頁面按鈕點擊觸發(fā)事件后panel滾動條非自動回到頂端,每次都要往下拉一下,關(guān)于這個問題的解決方法如下2014-11-11
asp.net core 集成swagger ui的原理解析
本文主要講解了如何對API進行分組,這里僅僅是舉了一個按照API功能進行分組的例子,其實在實際開發(fā)中,要按照何種方式分組,可以按照需求靈活定義,比如按照API版本進行分組2021-10-10
.NET?API?接口數(shù)據(jù)傳輸加密最佳實踐記錄
這篇文章主要介紹了.NET?API?接口數(shù)據(jù)傳輸加密最佳實踐記錄,我們在做?Api?接口時,相信一定會有接觸到要給傳輸?shù)恼埱?body?的內(nèi)容進行加密傳輸。其目的就是為了防止一些敏感的內(nèi)容直接被?UI?層查看或篡改,需要的朋友可以參考下2022-10-10
ASP.NET?Core?6框架揭秘實例演示之如何承載你的后臺服務(wù)
這篇文章主要介紹了ASP.NET?Core?6框架揭秘實例演示之如何承載你的后臺服務(wù),主要包括利用承載服務(wù)收集性能指標、依賴注入的應(yīng)用、配置選項的應(yīng)用等知識點,本文給大家介紹的非常詳細,需要的朋友可以參考下2022-03-03
ASP.NET頁面之間傳值的方式之Application實例詳解
這篇文章主要介紹了ASP.NET頁面之間傳值的方式之Application實例詳解,需要的朋友可以參考下2017-10-10

