EF-CodeFirst的优点
EF-CodeFirst相对于EF-ModelFirst和EF-DBFirst的有点在于,CodeFirst在数据库已经设计完成之后,能够较方便得再次对数据库进行更改(数据库迁移技术)。
关联
1.Database First是基于已存在的数据库,利用某些工具(如VS提供的EF设计器)创建实体类,数据库对象与实体类的匹配关系等,你也可以手动修改这些自动生成的代码及匹配文件。也就是从一个数据库开始,然后生成实体框架和相应代码。
2.Model First 是先利用某些工具(如VS的EF设计器)设计出可视化的实体数据模型及他们之间的关系,然后再根据这些实体、关系去生成数据库对象及相关代码文件。
3.Code First 这种方式需要先写一些代码,如实体对象,数据关系等,然后根据已有的代码描述,自动创建数据对象。但其实这种方法与Model First是非常类似的。我们自己写的代码,其实就是用代码表示实体模型,而Model First是用可视化的方式描述了实体模型。
EF-CodeFirst的具体实现过程(以17-3-2课后作业为对象分析)
Step1:按需求新建若干实体Entity
BaseEntity基类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF_CodeFirst_17_3_2.Model { public class BaseEntity { public BaseEntity() { CreateTime = DateTime.Now; UpdateTime = DateTime.Now; } /// <summary> /// 创建ID /// </summary> public int ID { get; set; } /// <summary> /// 创建人 /// </summary> public string CreateBy { get; set; } /// <summary> /// 创建时间 /// </summary> public DateTime CreateTime { get; set; } /// <summary> /// 更新人 /// </summary> public string UpdateBy { get; set; } /// <summary> /// 更新时间 /// </summary> public DateTime UpdateTime { get; set; } } } Classes班级实体 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF_CodeFirst_17_3_2.Model { public class Classes:BaseEntity { /// <summary> /// 班级编号 /// </summary> public int ClassNO { get; set; } /// <summary> /// 班级名称 /// </summary> public string ClassName { get; set; } /// <summary> /// 班主任ID /// </summary> public int MentorID { get; set; } /// <summary> /// 班主任名称 /// </summary> public virtual string MentorName { get; set; } /// <summary> /// 一个班级有多名学生 /// </summary> public virtual List<Student> students { get; set; } } } Course课程实体 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF_CodeFirst_17_3_2.Model { public class Course:BaseEntity { /// <summary> /// 课程编号 /// </summary> public int CourseNO { get; set; } /// <summary> /// 课程名称 /// </summary> public string CourseName { get; set; } /// <summary> /// 一个课程有多名学生 /// </summary> public virtual List<Student> students { get; set; } /// <summary> /// 一门课程有多个教师 /// </summary> public virtual List<Teacher> Teachers { get; set; } } } 学校School实体 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF_CodeFirst_17_3_2.Model { public class School : BaseEntity { /// <summary> /// 学校编号 /// </summary> public int SchoolNO { get; set; } /// <summary> /// 学校名称 /// </summary> public string SchoolName { get; set; } /// <summary> /// 校长ID /// </summary> public int HeadmasterID { get; set; } /// <summary> /// 校长名称 /// </summary> public string HeadmasterName { get; set; } /// <summary> /// 学校地址 /// </summary> public string Address_new { get; set; } } } 学生Student实体 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF_CodeFirst_17_3_2.Model { public class Student:BaseEntity { /// <summary> /// 学生编号 /// </summary> public int StudentNO { get; set; } /// <summary> /// 学生名称 /// </summary> public string StudentName { get; set; } /// <summary> /// 一个学生属于一个班级名称 /// </summary> public virtual Classes ClassName { get; set; } /// <summary> /// 一个学生有多门课程 /// </summary> public virtual List<Course> Courses { get; set; } } } 教师Teacher实体 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF_CodeFirst_17_3_2.Model { public class Teacher:BaseEntity { /// <summary> /// 教师编号 /// </summary> public int TeacherNO { get; set; } /// <summary> /// 教师名称 /// </summary> public string TeacherName { get; set; } /// <summary> /// 一个教师有多门课程 /// </summary> public virtual List<Course> Courses { get; set; } } }
Step2:建立各个实体之间的关联
比如 1 对 *,* 对 *等。
在代码上体现为:比如学生与班级的关系是:* 对 1。
则在实体Student内,存在一个班级对象。
即: /// <summary>
/// 一个学生属于一个班级名称
/// </summary>
public virtual Classes ClassName { get; set; }
而在Classes实体内,存在多个学生,即存在多个学生对象,所以我们用Lisk集合来保存这些对象。
即: /// 一个班级有多名学生
/// </summary>
public virtual List<Student> students { get; set; }
注意设置virtual属性。
Step3:在项目中引用EntityFramework
在项目中引用EntityFramework的两种方式:
1.通过 工具 > Nuget包管理器 > 管理解决方案的Nuget程序包,搜索EntityFramework在进行安装就行。
2.通过 工具 > Nuget包管理器 > 程序包管理控制台,输入“Install-Package EntityFramework”,也能自动完成EntityFramework的安装。
注意:不能通过复制EntityFramework的dll文件到项目文件夹下再进行引用。
Step4:配置App.config
<connectionStrings> <add name="DBConn" connectionString="Data Source=你的服务器地址; Connection Timeout=60;Initial Catalog=新的数据库名;Integrated Security=False;User ID=sa;Password=YourPassword;multipleactiveresultsets=True;" providerName="System.Data.SqlClient" /> </connectionStrings>
Step5:编写上下文
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Data.Entity; using EF_CodeFirst_17_3_2.Model; namespace EF_CodeFirst_17_3_2.EF { public class CodeFirstDBContext : DbContext { public CodeFirstDBContext() : base("name=DBConn") { this.Configuration.LazyLoadingEnabled = true; } static CodeFirstDBContext() { //一:数据库不存在时重新创建数据库[默认] Database.SetInitializer(new CreateDatabaseIfNotExists<CodeFirstDBContext>()); //二:每次启动应用程序时创建数据库 //Database.SetInitializer<testContext>(new DropCreateDatabaseAlways<SpreadtrumPMMContext>()); //三:策略三:模型更改时重新创建数据库 //Database.SetInitializer(new DropCreateDatabaseIfModelChanges<CodeFirstDBContext>()); //策略四:从不创建数据库 //Database.SetInitializer<CodeFirstDBContext>(null); } public virtual DbSet<Classes> Classes { get; set; } public virtual DbSet<Course> Course { get; set; } public virtual DbSet<School> School { get; set; } public virtual DbSet<Student> Student { get; set; } public virtual DbSet<Teacher> Teacher { get; set; } } }
到这里通过EF-CodeFirst构建的项目差不多完成了,运行之后数据库应该会新建一个你在App.config中配置的数据库以及所有的实体对应的表,以及中间表( * 对 * 关系会生成中间表 )。如果没有可能需要向数据库的某个表添加一条数据之后才会出来。
主程序:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using EF_CodeFirst_17_3_2.EF; using EF_CodeFirst_17_3_2.Model; namespace EF_CodeFirst_17_3_2 { class Program { static void Main(string[] args) { #region 添加学校信息 //using (CodeFirstDBContext dbContext = new CodeFirstDBContext()) //{ // School Ecjtu = new School(); // Ecjtu.SchoolName = "华东交通大学"; // Ecjtu.SchoolNO = 1; // Ecjtu.CreateBy = "Fnatic"; // Ecjtu.HeadmasterID = 1; // Ecjtu.HeadmasterName = "罗玉峰"; // Ecjtu.UpdateBy = "Fanatic"; // dbContext.School.Add(Ecjtu); // dbContext.SaveChanges(); //} #endregion #region 添加课程信息 //using (CodeFirstDBContext dbContext = new CodeFirstDBContext()) //{ // Course English = new Course(); // English.CourseName = "英语"; // English.CourseNO = 1; // English.CreateBy = "Fnatic"; // English.UpdateBy = "Fanatic"; // Course Math = new Course(); // Math.CourseName = "数学"; // Math.CourseNO = 2; // Math.CreateBy = "Fnatic"; // Math.UpdateBy = "Fanatic"; // dbContext.Course.Add(English); // dbContext.Course.Add(Math); // dbContext.SaveChanges(); //} #endregion #region 添加班级信息 //using (CodeFirstDBContext dbContext = new CodeFirstDBContext()) //{ // Classes classA = new Classes(); // classA.ClassName = "微创班"; // classA.ClassNO = 1; // classA.CreateBy = "Fnatic"; // classA.MentorID = 1; // classA.MentorName = "Mentor_A"; // classA.UpdateBy = "Fanatic"; // Classes classB = new Classes(); // classB.ClassName = "卓越班"; // classB.ClassNO = 2; // classB.CreateBy = "Fnatic"; // classB.MentorID = 2; // classB.MentorName = "Mentor_B"; // classB.UpdateBy = "Fanatic"; // dbContext.Classes.Add(classA); // dbContext.Classes.Add(classB); // dbContext.SaveChanges(); //} #endregion #region 添加教师信息 //using (CodeFirstDBContext dbContext = new CodeFirstDBContext()) //{ // Teacher T_A = new Teacher(); // T_A.CreateBy = "Fnatic"; // T_A.TeacherName = "Teacher_A"; // T_A.UpdateBy = "Fanatic"; // T_A.TeacherNO = 1; // dbContext.Teacher.Add(T_A); // dbContext.SaveChanges(); //} #endregion //Q:是向学生信息添加班级信息还是向班级信息添加学生信息 #region 添加学生信息并加入班级 //using (CodeFirstDBContext dbContext = new CodeFirstDBContext()) //{ // for (int i = 1; i <= 32; i++) // { // Student stu = new Student(); // stu.CreateBy = "Fnatic"; // stu.StudentName = "Student" + "_" + i; // stu.StudentNO = i; // stu.UpdateBy = "Fanatic"; // //获取班级 // Classes classes = dbContext.Classes.FirstOrDefault(u => u.ID == 1); // stu.ClassName = classes; // dbContext.Student.Add(stu); // dbContext.SaveChanges(); // } //} #endregion #region 教师教授课程的设置 //using (CodeFirstDBContext dbContext = new CodeFirstDBContext()) //{ // Teacher teacher = dbContext.Teacher.FirstOrDefault(u => u.ID == 1); // Course courseA = dbContext.Course.FirstOrDefault(u => u.ID == 1); // Course courseB=dbContext.Course.FirstOrDefault(u => u.ID == 2); // List<Course> course = new List<Course>(); // course.Add(courseA); // course.Add(courseB); // teacher.Courses = course; // dbContext.SaveChanges(); //} #endregion #region 学生选课 //using (CodeFirstDBContext dbContext = new CodeFirstDBContext()) //{ // Course courseA = dbContext.Course.FirstOrDefault(u => u.CourseNO == 1); // List<Course> course = new List<Course>(); // course.Add(courseA); // for (int i = 1; i <= 32; i++) // { // Student student = dbContext.Student.FirstOrDefault(u => u.StudentNO == i); // student.Courses = course; // } // dbContext.SaveChanges(); //} #endregion #region 添加学校地址之后再次添加学校信息 using (CodeFirstDBContext dbContext = new CodeFirstDBContext()) { //School Caida = new School(); //Caida.CreateBy = "Fnatic"; //Caida.HeadmasterID = 2; //Caida.HeadmasterName="王乔"; //Caida.SchoolName = "江西财经大学"; //Caida.SchoolNO = 2; //Caida.UpdateBy = "Fanatic"; //Caida.Address_new = "蛟桥镇"; //dbContext.School.Add(Caida); School Ecjtu = dbContext.School.FirstOrDefault(u => u.SchoolNO == 1); Ecjtu.Address_new = "江西省南昌市昌北双港东大街808号"; dbContext.SaveChanges(); } #endregion } } }
实体Entity做了更改的时候要做数据库迁移:
enable-Migrations -Force
Add-Migration demo
最后再次执行:Update-Database -Force
数据库会自动生成dbo.__MigrationHistory表来记录更新记录。
在项目下面也会自动生成Migrations文件夹,包括每一次的更新记录,以及Configuration。
关于项目内命名空间的问题:
1. 对于在项目根目录下:命名空间为项目名
2. 但是如果在项目下面新建了文件夹,则命名空间为“项目名.文件夹名”
所以在引用不用命名空间下的资源的时候需要首先引用命名空间。