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屬性上用 [
模型中,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的應用的基本介紹就到這里,更深入的學習還是參考微軟官方文檔吧
