前言:html
本系列文章主要爲我以前所學知識的一次微小的實踐,以我學校圖書館管理系統爲雛形所做。git
本系列文章主要參考資料:github
微軟文檔:https://docs.microsoft.com/zh-cn/aspnet/core/getting-started/?view=aspnetcore-2.1&tabs=windowssql
《Pro ASP.NET MVC 5》、《鋒利的 jQuery》數據庫
當此系列文章寫完後會在一週內推出修正版。json
此係列皆使用 VS2017+C# 做爲開發環境。若是有什麼問題或者意見歡迎在留言區進行留言。 windows
項目 github 地址:https://github.com/NanaseRuri/LibraryDemoapp
本章內容:對圖書館系統組成的簡要分析。以及對域模型以及相應數據庫的創建。ide
知識點:Code First、EF 基本使用方法、ASP.NET Core 使用 EF Core 的配置方法。函數
1、對圖書館系統域模型的分析
一個圖書館系統須要有管理員、 學生、書架以及書籍
域模型,即用來存儲數據的模型。
在此域模型能夠用如下結構建立:
2、項目結構
而後就能夠開始創建該項目了:
Docker支持和身份驗證在之後能夠自行添加,在此就不使用相應的支架特性。
所謂支架特性就是 VS2017 可以自動爲咱們完成一系列的工做的特性,固然這部分工做也能夠自行完成。
建立一個單元測試項目並引用 LibraryDemo 爲之後的單元測試作準備。
而後正式開始圖書館項目的編寫:
爲了辨識,我建立了這樣的文件夾結構,這裏的 Migrations 文件夾由後面提到的 EF 自動建立。
3、創建域模型
學位枚舉:
1 public enum Degrees 2 { 3 CollegeStudent, 4 Postgraduate, 5 DoctorateDegree 6 }
圖書借閱狀態枚舉:
1 public enum BookState 2 { 3 /// <summary> 4 /// 可借閱 5 /// </summary> 6 [Display(Name = "正常")] 7 Normal, 8 9 /// <summary> 10 /// 館內閱覽 11 /// </summary> 12 [Display(Name = "館內閱覽")] 13 Readonly, 14 15 /// <summary> 16 /// 已借出 17 /// </summary> 18 [Display(Name = "已借出")] 19 Borrowed, 20 21 /// <summary> 22 /// 被續借 23 /// </summary> 24 [Display(Name = "被續借")] 25 ReBorrowed, 26 27 /// <summary> 28 /// 被預定 29 /// </summary> 30 [Display(Name = "被預定")] 31 Appointed, 32 33 [Display(Name = "過時")] 34 Expired 35 }
學生信息:
1 public class Student 2 { 3 [Key] 4 public string Id { get; set; } 5 [Required] 6 public string Name { get; set; } 7 8 /// <summary> 9 /// 學位,用來限制借書數目 10 /// </summary> 11 [Required] 12 public Degrees Degree { get; set; } 13 14 /// <summary> 15 /// 最大借書數目 16 /// </summary> 17 [Required] 18 public int MaxBooksNumber { get; set; } 19 20 /// <summary> 21 /// 已借圖書 22 /// </summary> 23 public IEnumerable<Book> KeepingBooks { get; set; } 24 25 /// <summary> 26 /// 預定的書 27 /// </summary> 28 public string AppointingBookBarCode { get; set; } 29 30 /// <summary> 31 /// 罰款 32 /// </summary> 33 public decimal Fine { get; set; } 34 }
在約定中,若不指定主鍵,則 EF 會使用 (類名)+ID 的方式指定或建立主鍵,在此使用 [Key] 指定主鍵,使用 [Required] 指定字段爲必須,這種能夠爲屬性添加在數據庫中的約束或者在視圖中的約束的修飾稱爲 DataAnnotations 。
借閱書籍信息:
1 /// <summary> 2 /// 用於借閱的書籍信息 3 /// </summary> 4 public class Book 5 { 6 /// <summary> 7 /// 條形碼 8 /// </summary> 9 [Key][Required] 10 public string BarCode { get; set; } 11 12 public string ISBN { get; set; } 13 14 /// <summary> 15 /// 書名 16 /// </summary> 17 [Required] 18 public string Name { get; set; } 19 20 /// <summary> 21 /// 取書號 22 /// </summary> 23 public string FetchBookNumber { get; set; } 24 25 /// <summary> 26 /// 所在書架 27 /// </summary> 28 //public Bookshelf Bookshelf { get; set; } 29 public ICollection<BookMiddle> BookMiddles { get; set; } 30 31 /// <summary> 32 /// 借出時間 33 /// </summary> 34 public DateTime? BorrowTime { get; set; } 35 36 /// <summary> 37 /// 到期時間 38 /// </summary> 39 public DateTime? MatureTime { get; set; } 40 41 /// <summary> 42 /// 預定最晚借書日期 43 /// </summary> 44 public DateTime? AppointedLatestTime { get; set; } 45 46 /// <summary> 47 /// 借閱狀態 48 /// </summary> 49 public BookState State { get; set; } 50 51 /// <summary> 52 /// 持有者,指定外鍵 53 /// </summary> 54 public Student Keeper { get; set; } 55 }
書籍詳細信息:
1 /// <summary> 2 /// 書籍自身的詳細信息 3 /// </summary> 4 public class BookDetails 5 { 6 [Key] 7 public string ISBN { get; set; } 8 [Required] 9 public string Name { get; set; } 10 [Required] 11 public string Author { get; set; } 12 [Required] 13 public string Press { get; set; } 14 15 /// <summary> 16 /// 出版時間 17 /// </summary> 18 [Required] 19 public DateTime PublishDateTime{ get; set; } 20 21 /// <summary> 22 /// 書籍版本 23 /// </summary> 24 [Required] 25 public int Version { get; set; } 26 27 /// <summary> 28 /// 載體形態,包括頁數、媒介等信息 29 /// </summary> 30 public string SoundCassettes { get; set; } 31 32 /// <summary> 33 /// 簡介 34 /// </summary> 35 public string Description { get; set; } 36 }
書架信息:
1 public class Bookshelf 2 { 3 /// <summary> 4 /// 書架ID 5 /// </summary> 6 [Key] 7 public int BookshelfId { get; set; } 8 9 /// <summary> 10 /// 書架的書籍類別 11 /// </summary> 12 13 [Required] 14 public string Sort { get; set; } 15 /// <summary> 16 /// 最小取書號 17 /// </summary> 18 [Required] 19 public string MinFetchNumber { get; set; } 20 [Required] 21 public string MaxFetchNumber { get; set; } 22 23 /// <summary> 24 /// 書架位置 25 /// </summary> 26 [Required] 27 public string Location { get; set; } 28 29 /// <summary> 30 /// 所有藏書 31 /// </summary> 32 public ICollection<Book> Books { get; set; } 33 }
推薦書籍信息的結構與書籍詳細信息一致:
1 public class RecommendedBook 2 { 3 [Key] 4 public string ISBN { get; set; } 5 [Required] 6 public string Name { get; set; } 7 [Required] 8 public string Author { get; set; } 9 [Required] 10 public string Press { get; set; } 11 12 /// <summary> 13 /// 出版時間 14 /// </summary> 15 [Required] 16 public DateTime PublishDateTime { get; set; } 17 18 /// <summary> 19 /// 書籍版本 20 /// </summary> 21 [Required] 22 public int Version { get; set; } 23 24 /// <summary> 25 /// 載體形態,包括頁數、媒介等信息 26 /// </summary> 27 public string SoundCassettes { get; set; } 28 }
登陸所用信息(此處 Student 模型使用 ASP.NET Core 內建的 Identity,而 Admin 使用本身創建的邏輯):
1 public class Student:IdentityUser 2 { 3 /// <summary> 4 /// 學號 5 /// </summary> 6 [ProtectedPersonalData] 7 [RegularExpression("[UI]\\d{9}")] 8 public override string UserName { get; set; } 9 10 [Required] 11 public string Name { get; set; } 12 13 /// <summary> 14 /// 學位,用來限制借書數目 15 /// </summary> 16 [Required] 17 public Degrees Degree { get; set; } 18 19 /// <summary> 20 /// 最大借書數目 21 /// </summary> 22 [Required] 23 public int MaxBooksNumber { get; set; } 24 25 /// <summary> 26 /// 已借圖書 27 /// </summary> 28 public IEnumerable<Book> KeepingBooks { get; set; } 29 30 /// <summary> 31 /// 預定的書 32 /// </summary> 33 public string AppointingBookBarCode { get; set; } 34 35 [StringLength(14,MinimumLength = 11)] 36 public override string PhoneNumber { get; set; } 37 38 /// <summary> 39 /// 罰款 40 /// </summary> 41 public decimal Fine { get; set; } 42 }
1 public class Admin 2 { 3 [Key] 4 public string UserName { get; set; } 5 6 [Required] 7 public string PhoneNumber { get; set; } 8 9 [Required] 10 public string Email { get; set; } 11 12 [Required] 13 public string Password { get; set; } 14 }
4、建立 DbContext
根據約定,建立 DbContext 類爲 EF 提供創建的數據庫的結構:
1 public class StudentIdentityDbContext:IdentityDbContext<Student> 2 { 3 public StudentIdentityDbContext(DbContextOptions<StudentIdentityDbContext> options) : base(options) 4 { 5 } 6 }
1 public class AdminDbContext:DbContext 2 { 3 public AdminDbContext(DbContextOptions<AdminDbContext> options) : base(options) 4 { 5 } 6 7 public DbSet<Admin> Admins { get; set; } 8 }
1 public class LendingInfoDbContext:DbContext 2 { 3 public LendingInfoDbContext(DbContextOptions<LendingInfoDbContext> options) : base(options) 4 { 5 } 6 7 public DbSet<Book> Books { get; set; } 8 public DbSet<BookDetails> BooksDetail { get; set; } 9 public DbSet<Bookshelf> Bookshelves { get; set; } 10 public DbSet<Student> Students { get; set; } 11 public DbSet<RecommendedBook> RecommendedBooks { get; set; } 12 }
每一個 DbContext 類表明一個數據庫,每一個 DbSet<T> 表明一張表。而構造函數參數以及其形式爲 ASP.NET Core 的依賴注入的約定形式。
5、根據約定配置數據庫,進行依賴注入
在 appsettings.json 中添加數據庫鏈接字符串。
{ "ConnectionStrings": { "AdminDbContext": "Server=(localdb)\\mssqllocaldb;Database=AdminDbContext;Trusted_Connection=True;MultipleActiveResultSets=true", "LendingInfoDbContext": "Server=(localdb)\\mssqllocaldb;Database=LendingInfoDbContext;Trusted_Connection=True;MultipleActiveResultSets=true", "StudentIdentityDbContext": "Server=(localdb)\\mssqllocaldb;Database=StudentIdentityDbContext;Trusted_Connection=True;MultipleActiveResultSets=true" }, "Logging": { "LogLevel": { "Default": "Warning" } }, "AllowedHosts": "*" }
在 Startup.cs 中的 ConfigureServices 方法中對數據庫進行配置:
1 services.AddDbContext<LendingInfoDbContext>(options => 2 { 3 options.UseSqlServer(Configuration.GetConnectionString("LendingInfoDbContext")); 4 }); 5 services.AddDbContext<AdminDbContext>(options => 6 { 7 options.UseSqlServer(Configuration.GetConnectionString("AdminDbContext")); 8 }); 9 services.AddDbContext<StudentIdentityDbContext>(options => 10 { 11 options.UseSqlServer(Configuration.GetConnectionString("StudentIdentityDbContext")); 12 });
6、數據庫的遷移、建立及更新
而後在 pm控制檯 中添加遷移:
添加遷移的語法爲 add-migration <遷移類名> -c <具體 DbContext 名>
分別執行如下代碼:
1 cd LibraryDemo 2 add-migration Admin -c LibraryDemo.Data.AdminDbContext 3 add-migration LendingInfo -c LibraryDemo.Data.LendingInfoDbContext 4 add-migration StudentIdentity -c LibraryDemo.Data.StudentIdentityDbContext
運行 add-migration 命令會建立 Migrations 文件夾以及相應的遷移快照,此處的 AddSomeDetails 和 AddRequired 爲後來我本身添加的內容:
顯示的類名爲 <建立時間>_<遷移類名>,而實際的類名爲 add-migration 後的第一個參數名。
在建立遷移時,EF 會自動爲咱們建立或更新對應 DbContext 的快照,即其中後綴爲 Snapshot 的類。其中會包含當前對應的 DbCOntext 的結構,並會以代碼保留相應的約束,如 LendingInfoDbContextModelSnapshot 類:
生成的遷移類 LendingInfo 和 Account 類則有兩個方法—— 用於更新數據庫的 Up 方法和用以回溯數據庫的 Down 方法,能夠在這兩個方法或者在快照的 BuildModel 方法中使用 Fluent API 對數據庫作進一步的改動,而且經過對 Fluent API 的使用能夠使咱們的類少用 DataAnnotations 以保證類的整潔。
須要注意的是,生成的遷移類中的 Up 和 Down 方法是根據生成遷移以前的數據庫快照生成的,如我在以後爲 LendingInfoDbContext 添加 DbSet<RecommendedBook> 時,在以上的基礎上運行了 add-migration AddRecommendedBook -c LibraryDemo.Data.LendingInfoDbContext ,生成的 Up 方法只包括添加表 RecommendedBooks 的行爲,而 Down 方法只包括刪除表 RecommendedBooks 的行爲。
隨後在 pm控制檯 執行如下建立或更新數據庫:
1 update-database -c LibraryDemo.Data.AdminDbContext 2 update-database -c LibraryDemo.Data.LendingInfoDbContext 3 update-database -c LibraryDemo.Data.StudentIdentityDbContext
最後在 SQL server對象管理器 中能夠看見建立的數據庫以及對應的表:
至此域模型建立工做完成。
補充:
使用命令行對數據庫進行遷移及更新有兩種方式:
1 dotnet ef migrations migrationName -c TargetContext 2 dotnet ef database update -c TargetContext
1 add-migration migrationName -c TargetContext
2 update-Database -c TargetContext
windows 命令行命令不區分大小寫,其中 migrationName 爲遷移類名,最好提供有意義的命名;而 TargetContext 爲目標 DbContext 類名,須要使用帶有命名空間的徹底命名。
若是須要刪除數據庫則使用 drop 方法
drop-database -c TargetContext
而爲 update 方法指定遷移類則能夠回溯數據庫。
Update-Database LendingInfoDbContext -TargetMigration:"20181127081115_LendingInfo.cs"
原文出處:https://www.cnblogs.com/gokoururi/p/10158425.html