【EF6學習筆記】(一)Code First 方式生成數據庫及初始化數據庫實際操作


本篇參考原文地址:

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)]

        


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM