《ProASP.NETMVC5》、《锋利的jQuery》
此系列皆使用VS2017+C#作为开发环境。如果有什么问题或者意见欢迎在留言区进行留言。
本章内容:对图书馆系统组成的简要分析。以及对域模型以及相应数据库的建立。
知识点:CodeFirst、EF基本使用方法、ASP.NETCore使用EFCore的配置方法、EF多对多关系的建立、取消int主键自动增长。
一、对图书馆系统域模型的分析
一个图书馆系统需要有管理员、学生、书架以及书籍
域模型,即用来存储数据的模型。
在此域模型可以用以下结构创建:
二、项目结构
然后就可以开始建立该项目了:
三、建立域模型
学位枚举:
1publicenumDegrees2{3[Display(Name="本科生")]4CollegeStudent,5[Display(Name="研究生")]6Postgraduate,7[Display(Name="博士生")]8DoctorateDegree9}
图书借阅状态枚举:
1publicenumBookState2{3///
该项目准备使用一个数据库存储学生账户信息,另一个则用于存储学生借书信息:
学生账户信息:
1publicclassStudent:IdentityUser2{3///
书籍信息:
书架信息:
由于EF会自动将int类型的主键设置为自动增长,因此自定义Bookshelf的ID在插入数据库时会报错,在此需添加修饰[DatabaseGenerated(DatabaseGeneratedOption.None)]告知ef取消该设置:
1publicclassBookshelf2{3///
由于一个学生可以借阅多本书籍,一本书籍可被多人预约,因此书籍和学生具有多对多的关系,在此引入中间类:
其中的AppointingDateTime用来区分中间类包含的书籍是借阅书籍还是预约书籍:
1publicclassAppointmentOrLending2{3publicBookBook{get;set;}4publicstringBookId{get;set;}5publicStudentInfoStudent{get;set;}6publicstringStudentId{get;set;}7publicDateTimeAppointingDateTime{get;set;}8}
学生借书信息:
在EF中多对多关系实际上是两个多对一关系。此处ICollection的属性成为导航属性,用来提示EFStudentInfo和AppointmentOrLending之间存在着多对一的关系。
1publicclassStudentInfo2{3[Key]4publicstringUserName{get;set;}56[Required]7publicstringName{get;set;}89///
外借/阅览书籍信息:
在约定中,若不指定主键,则EF会使用(类名)+ID的方式指定或创建主键,在此使用[Key]指定主键,使用[Required]指定字段为必须,这种可以为属性添加在数据库中的约束或者在视图中的约束的修饰称为DataAnnotations。
此处ICollection的属性成为导航属性,用来提示EFBook和AppointmentOrLending之间存在着多对一的关系。
四、创建DbContext
学生账户信息数据库:
1publicclassStudentIdentityDbContext:IdentityDbContext
借阅信息数据库:
为了使StudentInfo类的UserName和Book的BarCode共同作为AppointmentOrLending中间类的主键,需覆写OnModelCreating方法:
至此StudentInfo和Book的多对多关系正式确立。
1publicclassLendingInfoDbContext:DbContext2{3publicLendingInfoDbContext(DbContextOptions
五、根据约定配置数据库,进行依赖注入
在appsettings.json中添加数据库连接字符串。
1{2"ConnectionStrings":{3"LendingInfoDbContext":"Server=(localdb)\\mssqllocaldb;Database=LendingInfoDbContext;Trusted_Connection=True;MultipleActiveResultSets=true",4"StudentIdentityDbContext":"Server=(localdb)\\mssqllocaldb;Database=StudentIdentityDbContext;Trusted_Connection=True;MultipleActiveResultSets=true"5},6"Logging":{7"LogLevel":{8"Default":"Warning"9}10},11"AllowedHosts":"*"12}
在Startup.cs中的ConfigureServices方法中对数据库进行配置:
1services.AddDbContext
六、数据库的迁移、创建及更新
然后在pm控制台中添加迁移:
添加迁移的语法为add-migration<迁移类名>-c<具体DbContext名>
运行add-migration命令会创建Migrations文件夹以及相应的迁移快照:
在创建迁移时,EF会自动为我们创建或更新对应DbContext的快照,即其中后缀为Snapshot的类。其中会包含当前对应的DbCOntext的结构,并会以代码保留相应的约束,如LendingInfoDbContextModelSnapshot类:
生成的迁移类LendingInfo和Account类则有两个方法——用于更新数据库的Up方法和用以回溯数据库的Down方法,可以在这两个方法或者在快照的BuildModel方法中使用FluentAPI对数据库做进一步的改动,并且通过对FluentAPI的使用可以使我们的类少用DataAnnotations以保证类的整洁。
需要注意的是,生成的迁移类中的Up和Down方法是根据生成迁移之前的数据库快照生成的,如我在之后为LendingInfoDbContext添加DbSet
随后在pm控制台执行以下创建或更新数据库:
1update-database-cLibraryDemo.Data.LendingInfoDbContext2update-database-cLibraryDemo.Data.StudentIdentityDbContext
最后在SQLserver对象管理器中可以看见创建的数据库以及对应的表:
至此域模型创建工作完成。
补充:
使用命令行对数据库进行迁移及更新有两种方式:
1dotnetefmigrationsmigrationName-cTargetContext2dotnetefdatabaseupdate-cTargetContext
1add-migrationmigrationName-cTargetContext2update-Database-cTargetContext
windows命令行命令不区分大小写,其中migrationName为迁移类名,最好提供有意义的命名;而TargetContext为目标DbContext类名,需要使用带有命名空间的完全命名。