EF-CodeFirst实现过程+数据库迁移

作者: 垃圾简书_吃枣药丸 | 来源:发表于2017-03-03 10:01 被阅读671次

    系列文章:

    EF-ModelFirst实现过程+数据库迁移     http://www.jianshu.com/p/2a53f318144d
    EF-DBFirst实现过程    http://www.jianshu.com/p/eb84ec814926
    建议学习路径 DBFirst->ModelFirst->CodeFirst

    思路:通过代码编写实体和关联,编写上下文,根据实体和关联生成数据库。

    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. 但是如果在项目下面新建了文件夹,则命名空间为“项目名.文件夹名”

     

    所以在引用不用命名空间下的资源的时候需要首先引用命名空间。

    更新:

    时间:2017-03-17

    codefirst在做数据库迁移的可能出现的错误:

    欢迎指正O(∩_∩)O~

    相关文章

      网友评论

        本文标题:EF-CodeFirst实现过程+数据库迁移

        本文链接:https://www.haomeiwen.com/subject/obdlgttx.html