asp.net core通過ef core來訪問數據庫,這裏用的是代碼優先,通過遷移來同步數據庫與模型。
環境:vs2017,win10,asp.net core 2.1
一、從建立asp.net core web項目開始
1、通過vs2017建立一個asp.net core web應用程序
2、在models文件夾下面創建一個student類,這個類用作數據模型,表示的是數據庫裏面的student表
public class Student
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid ID { set; get; }
[Required]
[MaxLength(30)]
public string Name { set; get; }
public int Age { set; get; }
public byte Sex { set; get; }
public string Remark { set; get; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime CreateDate { set; get; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime LastUpdate { set; get; }
}
關於表裏面的特性説明這裏暫時不管,等創建了數據庫後再來説明。
3、創建數據庫上下文
在項目中建立一個Data文件夾,創建一個類SqlServerContext
public class SqlServerContext : DbContext
{
public SqlServerContext(DbContextOptions<SqlServerContext> options)
: base(options)
{
}
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().ToTable("Student");
}
}
在 Entity Framework 中,實體集通常與數據表相對應,具體實體與表中的行相對應。當數據庫創建完成後, EF 創建一系列數據表,表名默認和 DbSet 屬性名相同。但可以在OnModelCreating方法中指定表名。
4、註冊數據庫上下文
打開 Startup.cs,在ConfigureServices方法中添加如下代碼
services.AddDbContext<SqlServerContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("SqlServerContext")));
SqlServerContext是數據庫字符串的名稱。打開appsettings.json 文件,並如以下示例所示添加連接字符串。
"ConnectionStrings": {
"SqlServerContext": "Server=(localdb)\\ProjectsV84;Database=TestDB1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
這裏連接的是本地數據庫,數據庫的驗證方式是windows驗證。
5、遷移
通過命令行接口 (CLI)執行遷移命令來實現遷移,在此之前,需要按照適用於命令行接口 (CLI) 的 EF 工具。注意: 必須通過編輯 .csproj 文件來安裝此包;不能使用 install-package 命令或包管理器 GUI。
若要編輯 .csproj 文件,可右鍵單擊解決方案資源管理器中的項目名稱,然後選擇“編輯EFCoreDB.csproj”,在ItemGroup裏面添加如下代碼
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
在項目所在的文件夾下打開cmd窗口,執行命令:dotnet ef migrations add CreateDB
命令執行成功的話,會在項目中添加一個文件夾Migrations
這裏面的兩個文件就是EF如何創建數據庫的,一般來説不需要手動去修改這兩個文件。
這時候,數據庫裏面還沒有相應的數據庫和表
在cmd中執行命令dotnet ef database update,成功執行後,就可以在數據庫裏面看到創建的數據庫和表了
6、分析
現在來看看student表的列和模型student的關係
系統默認ID是主鍵,這是一種約定,當然也可以在模型student的ID屬性上用 [Key]來修飾,這時候ID可以是其他的名稱。具體有關模型創建的信息,請參考創建並配置模型
模型中,ID的類型是guid,在數據庫裏面就對應類型uniqueidentifier,[DatabaseGenerated(DatabaseGeneratedOption.None)]特性表示ID列不需要數據庫自動添加值。
Name和Remark都是string類型,remark沒有任何修飾,所以數據庫中的類型就是nvarchar(max),且可以為空。
7、步驟優化
上面的的6個步驟中,第3,4兩步可以不用手動添加。可以通過新搭建基架的項目命令來完成。
先完成上面的1,2兩個步驟,然後在Controllers文件夾上右鍵==》添加==》新搭建基架的項目
在模型類中選擇第二步添加的模型student,數據上下文類中,點擊後面的+號,將名稱改為sqlserver,其他的默認就行,最後點擊添加。系統會自動的創建數據上下文,並且還幫你註冊了,除此之外,還添加了students控制器和相應的視圖,對於控制器和視圖可以保留,也可以刪掉。剩下的需要修改一下配置文件中數據庫的連接字符串,然後接着第五步繼續就可以了。
二、當模型修改或者添加新的模型後
1、修改模型student,添加一個學號字段code;添加模型course,每個學生可以報多個課程,每個課程可以有多個學生報名,因此student和course是多對多的關係,需要一箇中間表來關聯,所以添加模型Enrollment。修改後的模型如下:
public class Student
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public Guid ID { set; get; }
[Required]
[MaxLength(30)]
public string Name { set; get; }
[Required]
[MaxLength(30)]
public string Code { set; get; }
public int Age { set; get; }
public byte Sex { set; get; }
public string Remark { set; get; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public DateTime CreateDate { set; get; }
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime LastUpdate { set; get; }
public ICollection<Enrollment> Enrollments { get; set; }
}
public class Enrollment
{
public int EnrollmentID { get; set; }
public int CourseID { get; set; }
public Guid StudentID { get; set; }
public Grade? Grade { get; set; }
public Course Course { get; set; }
public Student Student { get; set; }
}
public enum Grade
{
A, B, C, D, F
}
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
public ICollection<Enrollment> Enrollments { get; set; }
}
修改數據上下文
public class SqlServerContext : DbContext
{
public SqlServerContext(DbContextOptions<SqlServerContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>().ToTable("Student");
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
}
public DbSet<Student> Students { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Course> Courses { get; set; }
}
2、遷移
執行這個命令後,在Migrations文件夾中添加了20190329030918_AddTable.cs文件,裏面的內容就是關於模型的修改的一些代碼
繼續執行命令dotnet ef database update
完事後,數據庫中表已經正常添加了
通過上面的方式,在student表中添加了列code,新建的表Enrollment中有主鍵和外鍵。當然也可以不用設置外鍵,直接將表Enrollment的CourseID和StudentID設置為複合主鍵。這樣的話,模型student中就不需要導航屬性StudentID(Course,Enrollment中也是如此)。同時數據上下文中需要指定Enrollment表的複合主鍵:
modelBuilder.Entity<Enrollment>().ToTable("Enrollment").HasKey(c=>new { c.StudentID,c.CourseID});
這樣一來,Enrollment中的EnrollmentID也要去掉。設置複合主鍵只能是在數據上下文中設置。
三、為數據庫添加初始數據
在數據庫中,有些表是有初始數據的,可以通過sql語句導入,在這裏通過程序來實現吧
打開Program.cs文件,修改後:
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<SqlServerContext>();
Initialize(context);
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
private static void Initialize(SqlServerContext context)
{
if (!context.Courses.Any())
{
var courses = new Course[]
{
new Course{CourseID=1050,Title="數學",Credits=3},
new Course{CourseID=4022,Title="語文",Credits=3},
new Course{CourseID=4041,Title="英語",Credits=3},
new Course{CourseID=1045,Title="化學",Credits=4},
new Course{CourseID=3141,Title="生物",Credits=4},
new Course{CourseID=2021,Title="物理",Credits=3},
new Course{CourseID=2042,Title="體育",Credits=4}
};
foreach (Course c in courses)
{
context.Courses.Add(c);
}
context.SaveChanges();
}
}
}
運行程序,數據就會添加到數據庫了。
四、數據庫表裏面有數據的情況下修改表結構
這裏的修改肯定是合理的修改,不能説你將字符串的列改成了數字的列。這裏試驗一下添加新的列,不能為空的
1、在course模型中,添加一個非空的字段
2、遷移
執行完遷移的第一個命令後,打開系統添加的文件,找到Up方法
可以看到up方法裏面只有影響修改的部分,要設置一個非空列的初始值,就需要在這裏改代碼了,改好了之後執行遷移的第二個命令。查詢數據庫,表結構已經更改,而且裏面的數據也沒有丟失。
關於EF CORE的應用的基本介紹就到這裏,更深入的學習還是參考微軟官方文檔吧