zoukankan      html  css  js  c++  java
  • EF6 学习笔记(一):Code First 方式生成数据库及初始化数据库实际操作

    EF6 学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)

    本篇参考原文地址:

    Creating an Entity Framework Data Model

    说明:学习笔记参考原文中的流程,为了增加实际操作性,并能够深入理解,部分地方根据实际情况做了一些调整;并且根据自己的理解做了一些扩展。

    本人的学习环境: VS2017 + EF 6.1.3 + .NET 4.6.1

    Step1 :  新建Web Application (我起名为EFTest)

    选择空白模板,但勾选 MVC 的Folder reference.

    Step2:  通过Package Manager Console来安装EF6

    Step3: 新建一个LocalDB的空的测试数据库

    Step4: 新建一个 主页面 作为基础入口(在Controller目录下新建一个空的Controller, 起名字就为Home 即可)

      

    然后在Home Controller的Index Action上右键点击来增加Index View: (就选空的View就可以,测试嘛,能简单就简单)

    并将Home/Index View中修改为以下代码:

    @{
        ViewBag.Title = "Hello EF6";
    }
    <h2>Hello EF6</h2>
    <div>
        <ul>
            <li>@Html.ActionLink("Home", "Index", "Home")</li>
            <li>@Html.ActionLink("About", "About", "Home")</li>
            <li>@Html.ActionLink("Students", "Index", "Student")</li>
            <li>@Html.ActionLink("Courses", "Index", "Course")</li>
            <li>@Html.ActionLink("Instructors", "Index", "Instructor")</li>
            <li>@Html.ActionLink("Departments", "Index", "Department")</li>
        </ul>
    </div>

    Step5: 在Web.config中增加 数据库字符串;

      <connectionStrings>
        <add name="SchoolContext" connectionString="Data Source=(localdb)ProjectsV13;Initial Catalog=EFTest;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=True;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;" providerName="System.Data.SqlClient"/>
      </connectionStrings>  

    注:可以点击 SQLServer Object Explorer中的数据库,然后在 属性页中,可以拷贝出该数据库的连接字符串;

     

     Step6: 正式开始EF学习测试相关的操作:

      6.1 在Models目录下新建 Student类

    using System;
    using System.Collections.Generic;
    
    namespace EFTest.Models
    {
        public class Student
        {
            public int ID { get; set; }
            public string LastName { get; set; }
            public string FirstMidName { get; set; }
            public DateTime EnrollmentDate { get; set; }
    
            public virtual ICollection<Enrollment> Enrollments { get; set; }
        }
    }

      6.2 在Models目录下新建Course类

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace EFTest.Models
    {
        public class Course
        {
            [DatabaseGenerated(DatabaseGeneratedOption.None)]
            public int CourseID { get; set; }
            public string Title { get; set; }
            public int Credits { get; set; }
    
            public virtual ICollection<Enrollment> Enrollments { get; set; }
        }
    }

      6.3 在Models目录下新建Enrollment类

    namespace EFTest.Models
    {
        public enum Grade
        {
            A, B, C, D, F
        }
    
        public class Enrollment
        {
            public int EnrollmentID { get; set; }
            public int CourseID { get; set; }
            public int StudentID { get; set; }
            public Grade? Grade { get; set; }
    
            public virtual Course Course { get; set; }
            public virtual Student Student { get; set; }
        }
    }

        通过类定义可以看到: 一个学生可以选修多个课程(有多个课程记录),一个课程可以多个学生选修(有多个学生记录);
        一个课程记录对应一个学生一门课程;

        那么对于课程记录,学生ID和课程ID就是外键;必须先存在某个学生,才可以有这个学生的课程记录,也必须先存在某个课程,才可以由这个课程的课程记录;

      6.4 新建一个DAL文件夹(数据访问层),新建 SchoolContext 类和SchoolInitializer类;

        说明:SchoolContext类从DbContext继承,并在构造函数中定义 数据库字符串名:base("SchoolContext") ,然后通过DbSet<T>定义数据库模型;

                最后还重载了OnModelCreating方法,用来改变一些约束;(如果例子中的表名不用变复数,以及其它约束,比如改表名、列名等等);   

    using EFTest.Models;
    using System.Data.Entity;
    using System.Data.Entity.ModelConfiguration.Conventions;
    
    namespace EFTest.DAL
    {
        public class SchoolContext : DbContext
        {
            public SchoolContext() : base("SchoolContext")
            {
            }
    
            public DbSet<Student> Students { get; set; }
            public DbSet<Enrollment> Enrollments { get; set; }
            public DbSet<Course> Courses { get; set; }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            }
        }
    }

        说明:SchoolInitializer类用来定义数据库在初始化的时候需要做的一些事情;比如通过重载Seed方法预先放入一些数据等;

    using System;
    using System.Collections.Generic;
    using EFTest.Models;
    
    namespace EFTest.DAL
    {
        public class SchoolInitializer : System.Data.Entity.DropCreateDatabaseIfModelChanges<SchoolContext>
        {
            protected override void Seed(SchoolContext context)
            {
                var students = new List<Student>
                {
                new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
                new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
                new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
                new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
                new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
                new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
                new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
                new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
                };
    
                students.ForEach(s => context.Students.Add(s));
                context.SaveChanges();
                var courses = new List<Course>
                {
                new Course{CourseID=1050,Title="Chemistry",Credits=3,},
                new Course{CourseID=4022,Title="Microeconomics",Credits=3,},
                new Course{CourseID=4041,Title="Macroeconomics",Credits=3,},
                new Course{CourseID=1045,Title="Calculus",Credits=4,},
                new Course{CourseID=3141,Title="Trigonometry",Credits=4,},
                new Course{CourseID=2021,Title="Composition",Credits=3,},
                new Course{CourseID=2042,Title="Literature",Credits=4,}
                };
                courses.ForEach(s => context.Courses.Add(s));
                context.SaveChanges();
                var enrollments = new List<Enrollment>
                {
                new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
                new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
                new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
                new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
                new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
                new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
                new Enrollment{StudentID=3,CourseID=1050},
                new Enrollment{StudentID=4,CourseID=1050,},
                new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
                new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
                new Enrollment{StudentID=6,CourseID=1045},
                new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
                };
                enrollments.ForEach(s => context.Enrollments.Add(s));
                context.SaveChanges();
            }
        }
    }

    Step7:  定义数据库初始化(本章不涉及数据库迁移等,迁移以后再说)

       第6步定义了上下文类以及初始化类,那么怎么让应用在执行时候进行数据库初始化动作?

         有两种方式:(只能选一种)

         1、在Web.config 中定义:

                     在<entityFramework>节点中,增加<contexts>节点,分别定义<context>的type ,以及初始化<databaseInitializer>的type:  (具体为啥这样定义,只能以后看原理。。。)

    <entityFramework>
        <contexts>
          <context type="EFTest.DAL.SchoolContext, EFTest">
            <databaseInitializer type="EFTest.DAL.SchoolInitializer, EFTest" />
          </context>
        </contexts>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
          <parameters>
            <parameter value="mssqllocaldb" />
          </parameters>
        </defaultConnectionFactory>
        <providers>
          <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
        </providers>
      </entityFramework>

         2、在Global.asax中执行初始化;在Application_Start()方法中,最后加上以下数据库初始化代码:

        Database.SetInitializer<SchoolContext>(new SchoolInitializer());

      注:第1种方法,在Home/Index页面打开的时候是不会初始化数据库的,因为还没操作数据库读写。。。下面加访问页面来进行数据库读取;

    Step8: 增加一个 Student Controller  , 直接选择空白的就可以,通过敲入代码来更多理解:

    先为Student控制器加一个SchoolContext db , 然后把Student/Index的return View()改为如下:

    using EFTest.DAL;
    using System.Linq;
    using System.Web.Mvc;
    
    namespace EFTest.Controllers
    {
        public class StudentController : Controller
        {
            private SchoolContext db = new SchoolContext();
    
            // GET: Student
            public ActionResult Index()
            {
                return View(db.Students.ToList());
            }
        }
    }

    为Index Action加View, 选择List模板 , Model 选Student , 然后再选择好上下文类:

    注:如果出现以下错误,则表示先要编译一下,再建View

    Step9: 执行起来看看 Student/Index 页面:

    也可以查看一下数据库,已经新建成功:

    学习整理总结:

      1、根据ASP.NET MVC的概念,约定大于配置,EF6同样存在;

          数据类定义中,如果名为ID的,则自动为主键,如果为类名+ID的,也会自动为主键; 其他属性名自动为列表;如果为int型,则会默认为自增长主键;

          比较神奇的是外键的自动创建,这个约束描述起来好累,实际看看代码和实际数据库的外键就能明白;

           (通过加 virtual 描述来实现延时数据加载,即程序用到这个属性定义的数据时,才会去查数据库)

      2、 既然有约定就可以改变约定;

          可以通过对属性增加 Annotations注释 来改变约定,例如:修改主键不要为自增加主键,改变列表,增加其他列为主键,设定字段长度等等;

          如:[DatabaseGenerated(DatabaseGeneratedOption.None)]

            

  • 相关阅读:
    You are not late! You are not early!
    在同一个服务器(同一个IP)为不同域名绑定的免费SSL证书
    Vue.js Is Good, but Is It Better Than Angular or React?
    It was not possible to find any compatible framework version
    VS增加插件 Supercharger破解教程
    Git使用ssh key
    Disconnected: No supported authentication methods available (server sent: publickey)
    VS 2013打开.edmx文件时报类型转换异常
    asp.net MVC4 框架揭秘 读书笔记系列3
    asp.net MVC4 框架揭秘 读书笔记系列2
  • 原文地址:https://www.cnblogs.com/jacky-zhang/p/7373607.html
Copyright © 2011-2022 走看看