教學課程:使用 MVC 5 開始使用 Entity Framework 6 Code FirstTutorial: Get Started with Entity Framework 6 Code First using MVC 5

Note

針對新的開發,建議ASP.NET Core Razor Pages ASP.NET MVC 控制器和 views。For new development, we recommend ASP.NET Core Razor Pages over ASP.NET MVC controllers and views. 如需與使用 Razor Pages 類似的教學課程系列,請參閱教學課程:開始使用 ASP.NET Core 中的 Razor PagesFor a tutorial series similar to this one using Razor Pages, see Tutorial: Get started with Razor Pages in ASP.NET Core. 新的教學課程:The new tutorial:

  • 比較容易學習。Is easier to follow.
  • 提供更多 EF Core 最佳做法。Provides more EF Core best practices.
  • 使用更有效率的查詢。Uses more efficient queries.
  • 具有最新的 API。Is more current with the latest API.
  • 涵蓋更多功能。Covers more features.
  • 是新應用程式開發的建議方法。Is the preferred approach for new application development.

在這一系列的教學課程中,您將瞭解如何建立 ASP.NET MVC 5 應用程式,以使用 Entity Framework 6 來進行資料存取。In this series of tutorials, you learn how to build an ASP.NET MVC 5 application that uses Entity Framework 6 for data access. 本教學課程使用 Code First 工作流程。This tutorial uses the Code First workflow. 如需如何在 Code First、Database First 和 Model First 之間進行選擇的詳細資訊,請參閱建立模型For information about how to choose between Code First, Database First, and Model First, see Create a model.

本教學課程系列會說明如何建立 Contoso 大學範例應用程式。This tutorial series explains how to build the Contoso University sample application. 範例應用程式是簡單的大學網站。The sample application is a simple university website. 有了它,您就可以查看和更新學生、課程和講師資訊。With it, you can view and update student, course, and instructor information. 以下是您所建立的兩個畫面:Here are two of the screens you create:

Students_Index_page

編輯學生

在本教學課程中,您已:In this tutorial, you:

  • 建立 MVC web 應用程式Create an MVC web app
  • 設定網站樣式Set up the site style
  • 安裝 Entity Framework 6Install Entity Framework 6
  • 建立資料模型Create the data model
  • 建立資料庫內容Create the database context
  • 使用測試資料將 DB 初始化Initialize DB with test data
  • 設定 EF 6 使用 LocalDBSet up EF 6 to use LocalDB
  • 建立控制器和檢視Create controller and views
  • 檢視資料庫View the database

PrerequisitesPrerequisites

建立 MVC web 應用程式Create an MVC web app

  1. 開啟 Visual Studio,並使用C# ASP.NET web 應用程式(.NET Framework) 範本建立 Web 專案。Open Visual Studio and create a C# web project using the ASP.NET Web Application (.NET Framework) template. 將專案命名為ContosoUniversity ,然後選取 [確定]Name the project ContosoUniversity and select OK.

    Visual Studio 中的 [新增專案] 對話方塊

  2. 在 [新增 ASP.NET Web 應用程式-ContosoUniversity] 中,選取 [ MVC]。In New ASP.NET Web Application - ContosoUniversity, select MVC.

    Visual Studio 中的 [新增 web 應用程式] 對話方塊

    Note

    根據預設,驗證選項會設定為 [不需要驗證]。By default, the Authentication option is set to No Authentication. 在本教學課程中,web 應用程式不需要使用者登入。For this tutorial, the web app doesn't require users to sign in. 此外,它也不會根據登入的使用者來限制存取權。Also, it doesn't restrict access based on who's signed in.

  3. 選取 [確定] 建立專案。Select OK to create the project.

設定網站樣式Set up the site style

一些簡單的變更會設定網站的功能表、配置和首頁。A few simple changes will set up the site menu, layout, and home page.

  1. 開啟Views\Shared\_Layout,並進行下列變更:Open Views\Shared\_Layout.cshtml, and make the following changes:

    • 將每個出現的「我的 ASP.NET 應用程式」和「應用程式名稱」變更為「Contoso 大學」。Change each occurrence of "My ASP.NET Application" and "Application name" to "Contoso University".
    • 新增學生、課程、講師和部門的功能表項目,並刪除連絡人項目。Add menu entries for Students, Courses, Instructors, and Departments, and delete the Contact entry.

    這些變更會反白顯示在下列程式碼片段中:The changes are highlighted in the following code snippet:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>@ViewBag.Title - Contoso University</title>
        @Styles.Render("~/Content/css")
        @Scripts.Render("~/bundles/modernizr")
    </head>
    <body>
        <div class="navbar navbar-inverse navbar-fixed-top">
            <div class="navbar-inner">
                <div class="container">
                    <button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                        <span class="icon-bar"></span>
                    </button>
                    @Html.ActionLink("Contoso University", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
                    <div class="nav-collapse collapse">
                        <ul class="nav">
                            <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>
                </div>
            </div>
        </div>
    
        <div class="container">
            @RenderBody()
            <hr />
            <footer>
                <p>&copy; @DateTime.Now.Year - Contoso University</p>
            </footer>
        </div>
    
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/bootstrap")
        @RenderSection("scripts", required: false)
    </body>
    </html>
    
  2. Views\Home\Index.cshtml中,將檔案的內容取代為下列程式碼,以將 ASP.NET 和 MVC 的文字取代為此應用程式的文字:In Views\Home\Index.cshtml, replace the contents of the file with the following code to replace the text about ASP.NET and MVC with text about this application:

    @{
        ViewBag.Title = "Home Page";
    }
    
    <div class="jumbotron">
        <h1>Contoso University</h1>
    </div>
    <div class="row">
        <div class="col-md-4">
            <h2>Welcome to Contoso University</h2>
            <p>Contoso University is a sample application that
            demonstrates how to use Entity Framework 6 in an 
            ASP.NET MVC 5 web application.</p>
        </div>
        <div class="col-md-4">
            <h2>Build it from scratch</h2>
            <p>You can build the application by following the steps in the tutorial series on the ASP.NET site.</p>
            <p><a class="btn btn-default" href="http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/">See the tutorial &raquo;</a></p>
        </div>
        <div class="col-md-4">
            <h2>Download it</h2>
            <p>You can download the completed project.</p>
            <p><a class="btn btn-default" href="https://webpifeed.blob.core.windows.net/webpifeed/Partners/ASP.NET%20MVC%20Application%20Using%20Entity%20Framework%20Code%20First.zip">Download &raquo;</a></p>
        </div>
    </div>
    
  3. 按 Ctrl + F5 執行網站。Press Ctrl+F5 to run the web site. 您會在首頁上看到主功能表。You see the home page with the main menu.

安裝 Entity Framework 6Install Entity Framework 6

  1. 從 [工具] 功能表中,選擇 [ NuGet 套件管理員],然後選擇 [套件管理員主控台]。From the Tools menu, choose NuGet Package Manager, and then choose Package Manager Console.

  2. 在 [Package Manager Console] 視窗中,輸入下列命令:In the Package Manager Console window, enter the following command:

    Install-Package EntityFramework
    

此步驟是本教學課程的幾個步驟中的其中一個,但這可能是由 ASP.NET MVC 樣板功能自動完成的。This step is one of a few steps that this tutorial has you do manually, but that could have been done automatically by the ASP.NET MVC scaffolding feature. 您要手動執行這些動作,讓您可以看到使用 Entity Framework (EF)所需的步驟。You're doing them manually so that you can see the steps required to use Entity Framework (EF). 您稍後會使用此架構來建立 MVC 控制器和 views。You'll use scaffolding later to create the MVC controller and views. 替代方式是讓 [架構] 自動安裝 EF NuGet 封裝、建立資料庫內容類別,並建立連接字串。An alternative is to let scaffolding automatically install the EF NuGet package, create the database context class, and create the connection string. 當您準備好這樣做時,您只需要略過這些步驟,並在建立實體類別之後 scaffold 您的 MVC 控制器。When you're ready to do it that way, all you have to do is skip those steps and scaffold your MVC controller after you create your entity classes.

建立資料模型Create the data model

接下來您會為 Contoso 大學應用程式建立實體類別。Next you'll create entity classes for the Contoso University application. 您將從下列三個實體開始:You'll start with the following three entities:

課程 <-> 註冊 <-> StudentCourse <-> Enrollment <-> Student

實體Entities RelationshipRelationship
註冊課程Course to Enrollment 一對多One-to-many
要註冊的學生Student to Enrollment 一對多One-to-many

StudentEnrollment 實體之間存在一對多關聯性,CourseEnrollment 實體之間也存在一對多關聯性。There's a one-to-many relationship between Student and Enrollment entities, and there's a one-to-many relationship between Course and Enrollment entities. 換句話說,一位學生可以註冊並參加任何數目的課程,而一個課程也可以有任何數目的學生註冊。In other words, a student can be enrolled in any number of courses, and a course can have any number of students enrolled in it.

在下列各節中,您將為每個實體建立一個類別。In the following sections, you'll create a class for each one of these entities.

Note

如果您在完成所有這些實體類別的建立之前嘗試編譯專案,您會收到編譯器錯誤。If you try to compile the project before you finish creating all of these entity classes, you'll get compiler errors.

Student 實體The Student entity

  • 在 [模型] 資料夾中,建立名為Student.cs的類別檔案,方法是以滑鼠右鍵按一下方案總管中的資料夾,然後選擇 [加入 > 類別]。In the Models folder, create a class file named Student.cs by right-clicking on the folder in Solution Explorer and choosing Add > Class. 使用下列程式碼取代範本程式碼:Replace the template code with the following code:

    using System;
    using System.Collections.Generic;
    
    namespace ContosoUniversity.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; }
        }
    }
    

ID 屬性會成為資料庫資料表中的主索引鍵資料行,並對應至這個類別。The ID property will become the primary key column of the database table that corresponds to this class. 根據預設,Entity Framework 會將名為 IDclassname ID 的屬性解讀為主要索引鍵。By default, Entity Framework interprets a property that's named ID or classname ID as the primary key.

Enrollments 屬性為導覽屬性The Enrollments property is a navigation property. 導覽屬性會保留與此實體相關的其他實體。Navigation properties hold other entities that are related to this entity. 在此情況下,Student 實體的 Enrollments 屬性會保存與該 Student 實體相關的所有 Enrollment 實體。In this case, the Enrollments property of a Student entity will hold all of the Enrollment entities that are related to that Student entity. 換句話說,如果資料庫中給定的 Student 資料列有兩個相關的 Enrollment 列(在其 StudentID 外鍵資料行中包含該學生的主鍵值的資料列),該 Student 實體的 Enrollments 導覽屬性會包含這兩個 Enrollment 的實體。In other words, if a given Student row in the database has two related Enrollment rows (rows that contain that student's primary key value in their StudentID foreign key column), that Student entity's Enrollments navigation property will contain those two Enrollment entities.

導覽屬性通常會定義為 virtual,讓它們可以利用某些 Entity Framework 的功能,例如消極式載入Navigation properties are typically defined as virtual so that they can take advantage of certain Entity Framework functionality such as lazy loading. (稍後將在本系列稍後的讀取相關資料教學課程中說明消極式載入)。(Lazy loading will be explained later, in the Reading Related Data tutorial later in this series.)

若導覽屬性可保有多個實體 (例如在多對多或一對多關聯性中的情況),其類型必須為一個清單,使得實體可以在該清單中新增、刪除或更新,例如 ICollectionIf a navigation property can hold multiple entities (as in many-to-many or one-to-many relationships), its type must be a list in which entries can be added, deleted, and updated, such as ICollection.

Enrollment 實體The Enrollment entity

  • Models 資料夾中,建立 Enrollment.cs,然後使用下列程式碼取代現有的程式碼:In the Models folder, create Enrollment.cs and replace the existing code with the following code:

    namespace ContosoUniversity.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; }
        }
    }
    

EnrollmentID 屬性將會是主要金鑰;這個實體會使用classname ID 模式,而不是由您在 Student 實體中看到的本身 IDThe EnrollmentID property will be the primary key; this entity uses the classname ID pattern instead of ID by itself as you saw in the Student entity. 通常您會選擇一個模式,然後在您整個資料模型中使用此模式。Ordinarily you would choose one pattern and use it throughout your data model. 在這裡,此變化僅作為向您展示使用不同模式之用。Here, the variation illustrates that you can use either pattern. 在稍後的教學課程中,您將瞭解如何使用 ID 而不 classname,讓您更輕鬆地在資料模型中執行繼承。In a later tutorial, you'll see how using ID without classname makes it easier to implement inheritance in the data model.

Grade 屬性是列舉The Grade property is an enum. Grade 型別宣告後方的問號表示 Grade 屬性可為 NullThe question mark after the Grade type declaration indicates that the Grade property is nullable. Null 的等級與零的等級不同-null 表示不知道等級或尚未指派。A grade that's null is different from a zero grade — null means a grade isn't known or hasn't been assigned yet.

StudentID 屬性是外部索引鍵,對應的導覽屬性是 StudentThe StudentID property is a foreign key, and the corresponding navigation property is Student. Enrollment 實體與一個 Student 實體關聯,因此屬性僅能保有單一 Student 實體 (不像您先前看到的 Student.Enrollments 導覽屬性可保有多個 Enrollment 實體)。An Enrollment entity is associated with one Student entity, so the property can only hold a single Student entity (unlike the Student.Enrollments navigation property you saw earlier, which can hold multiple Enrollment entities).

CourseID 屬性是外部索引鍵,對應的導覽屬性是 CourseThe CourseID property is a foreign key, and the corresponding navigation property is Course. 一個 Enrollment 實體與一個 Course 實體建立關聯。An Enrollment entity is associated with one Course entity.

Entity Framework 將屬性(property)<導覽屬性名稱命名為「外鍵屬性」, ><主鍵屬性名稱> (例如 StudentID Student 實體的主要索引鍵 Student 後,ID導覽屬性的)。Entity Framework interprets a property as a foreign key property if it's named <navigation property name><primary key property name> (for example, StudentID for the Student navigation property since the Student entity's primary key is ID). 外鍵屬性也可以命名為相同 <主鍵屬性名稱> (例如 CourseID,因為 Course 實體的主要索引鍵是 CourseID)。Foreign key properties can also be named the same simply <primary key property name> (for example, CourseID since the Course entity's primary key is CourseID).

Course 實體The Course entity

  • 在 [模型] 資料夾中,建立Course.cs,將範本程式碼取代為下列程式碼:In the Models folder, create Course.cs, replacing the template code with the following code:

    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations.Schema;
    
    namespace ContosoUniversity.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; }
        }
    }
    

Enrollments 屬性為導覽屬性。The Enrollments property is a navigation property. Course 實體可以與任何數量的 Enrollment 實體相關。A Course entity can be related to any number of Enrollment entities.

我們將在本系列稍後的教學課程中,進一步瞭解 DatabaseGeneratedAttribute 屬性。We'll say more about the DatabaseGeneratedAttribute attribute in a later tutorial in this series. 基本上,此屬性可讓您為課程輸入主索引鍵,而非讓資料庫產生它。Basically, this attribute lets you enter the primary key for the course rather than having the database generate it.

建立資料庫內容Create the database context

協調給定資料模型 Entity Framework 功能的主要類別是資料庫內容類。The main class that coordinates Entity Framework functionality for a given data model is the database context class. 您可以藉由衍生自DbCoNtext類別來建立此類別。You create this class by deriving from the System.Data.Entity.DbContext class. 在您的程式碼中,您可以指定要包含在資料模型中的實體。In your code, you specify which entities are included in the data model. 您也可以自訂某些 Entity Framework 行為。You can also customize certain Entity Framework behavior. 在此專案中,類別命名為 SchoolContextIn this project, the class is named SchoolContext.

  • 若要在 ContosoUniversity 專案中建立資料夾,請以滑鼠右鍵按一下方案總管中的專案,然後按一下 [加入],再按一下 [新增資料夾]。To create a folder in the ContosoUniversity project, right-click the project in Solution Explorer and click Add, and then click New Folder. 將新資料夾命名為DAL (適用于資料存取層)。Name the new folder DAL (for Data Access Layer). 在該資料夾中,建立名為SchoolCoNtext.cs的新類別檔案,並以下列程式碼取代範本程式碼:In that folder, create a new class file named SchoolContext.cs, and replace the template code with the following code:

    using ContosoUniversity.Models;
    using System.Data.Entity;
    using System.Data.Entity.ModelConfiguration.Conventions;
    
    namespace ContosoUniversity.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>();
            }
        }
    }
    

指定實體集Specify entity sets

此程式碼會為每個實體集建立DbSet屬性。This code creates a DbSet property for each entity set. 在 Entity Framework 術語中,實體集通常會對應至資料庫資料表,而實體會對應到資料表中的資料列。In Entity Framework terminology, an entity set typically corresponds to a database table, and an entity corresponds to a row in the table.

Note

您可以省略 DbSet<Enrollment>DbSet<Course> 語句,它的作用相同。You can omit the DbSet<Enrollment> and DbSet<Course> statements and it would work the same. Entity Framework 會隱含地包含這些專案,因為 Student 實體會參考 Enrollment 實體,而 Enrollment 實體會參考 Course 實體。Entity Framework would include them implicitly because the Student entity references the Enrollment entity and the Enrollment entity references the Course entity.

指定連接字串Specify the connection string

連接字串的名稱(您稍後將會加入 web.config 檔案中)會傳遞至該函式。The name of the connection string (which you'll add to the Web.config file later) is passed in to the constructor.

public SchoolContext() : base("SchoolContext")
{
}

您也可以傳入連接字串本身,而不是儲存在 web.config 檔案中的名稱。You could also pass in the connection string itself instead of the name of one that is stored in the Web.config file. 如需指定要使用的資料庫之選項的詳細資訊,請參閱連接字串和模型For more information about options for specifying the database to use, see Connection strings and models.

如果您未明確指定連接字串或名稱,Entity Framework 會假設連接字串名稱與類別名稱相同。If you don't specify a connection string or the name of one explicitly, Entity Framework assumes that the connection string name is the same as the class name. 此範例中的預設連接字串名稱會 SchoolContext,與您明確指定的相同。The default connection string name in this example would then be SchoolContext, the same as what you're specifying explicitly.

指定單數資料表名稱Specify singular table names

OnModelCreating方法中的 modelBuilder.Conventions.Remove 語句會防止複數化資料表名稱。The modelBuilder.Conventions.Remove statement in the OnModelCreating method prevents table names from being pluralized. 如果您未這麼做,則資料庫中產生的資料表會命名為 StudentsCoursesEnrollmentsIf you didn't do this, the generated tables in the database would be named Students, Courses, and Enrollments. 相反地,資料表名稱會是 StudentCourseEnrollmentInstead, the table names will be Student, Course, and Enrollment. 針對是否要複數化資料表名稱,開發人員並沒有共識。Developers disagree about whether table names should be pluralized or not. 本教學課程使用單數形式,但重點在於,您可以藉由包含或省略這行程式碼來選取您偏好的任何格式。This tutorial uses the singular form, but the important point is that you can select whichever form you prefer by including or omitting this line of code.

使用測試資料將 DB 初始化Initialize DB with test data

Entity Framework 可以在應用程式執行時,自動為您建立(或卸載並重新建立)資料庫。Entity Framework can automatically create (or drop and re-create) a database for you when the application runs. 您可以指定每次執行應用程式時,或只有在模型與現有資料庫不同步時,才會執行此作業。You can specify that this should be done every time your application runs or only when the model is out of sync with the existing database. 您也可以撰寫 Seed 方法,Entity Framework 在建立資料庫之後自動呼叫,以便將測試資料填入其中。You can also write a Seed method that Entity Framework automatically calls after creating the database in order to populate it with test data.

預設行為是只在資料庫不存在時才建立它(如果模型已變更且資料庫已經存在,則會擲回例外狀況)。The default behavior is to create a database only if it doesn't exist (and throw an exception if the model has changed and the database already exists). 在本節中,您將指定每當模型變更時,應該卸載並重新建立資料庫。In this section, you'll specify that the database should be dropped and re-created whenever the model changes. 卸載資料庫會導致所有資料遺失。Dropping the database causes the loss of all your data. 這在開發期間通常是正常的,因為當重新建立資料庫時,會執行 Seed 方法,並重新建立您的測試資料。This is generally okay during development, because the Seed method will run when the database is re-created and will re-create your test data. 但是在生產環境中,您通常不會想要在每次需要變更資料庫架構時遺失所有資料。But in production you generally don't want to lose all your data every time you need to change the database schema. 稍後您會看到如何使用 Code First 移轉變更資料庫架構,而不是卸載並重新建立資料庫,以處理模型變更。Later you'll see how to handle model changes by using Code First Migrations to change the database schema instead of dropping and re-creating the database.

  1. 在 DAL 資料夾中,建立名為SchoolInitializer.cs的新類別檔案,並將範本程式碼取代為下列程式碼,這會在需要時建立資料庫,並將測試資料載入至新的資料庫。In the DAL folder, create a new class file named SchoolInitializer.cs and replace the template code with the following code, which causes a database to be created when needed and loads test data into the new database.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Data.Entity;
    using ContosoUniversity.Models;
    
    namespace ContosoUniversity.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();
            }
        }
    }
    

    Seed 方法會將資料庫內容物件當做輸入參數,而方法中的程式碼會使用該物件將新的實體加入至資料庫。The Seed method takes the database context object as an input parameter, and the code in the method uses that object to add new entities to the database. 針對每個實體類型,程式碼會建立新實體的集合,並將其加入適當的 DbSet 屬性,然後將變更儲存至資料庫。For each entity type, the code creates a collection of new entities, adds them to the appropriate DbSet property, and then saves the changes to the database. 在每個實體群組之後,都不需要呼叫 SaveChanges 方法,但在這裡完成這項作業,但如果程式碼寫入資料庫時發生例外狀況,就會協助您找出問題的來源。It isn't necessary to call the SaveChanges method after each group of entities, as is done here, but doing that helps you locate the source of a problem if an exception occurs while the code is writing to the database.

  2. 若要告知 Entity Framework 使用您的初始化運算式類別,請將專案新增至應用程式web.config檔案中的 entityFramework 元素(根專案資料夾中的),如下列範例所示:To tell Entity Framework to use your initializer class, add an element to the entityFramework element in the application Web.config file (the one in the root project folder), as shown in the following example:

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

    context type 會指定完整的內容類別名稱及其所在的元件,而 databaseinitializer type 會指定初始化運算式類別及其所在元件的完整名稱。The context type specifies the fully qualified context class name and the assembly it's in, and the databaseinitializer type specifies the fully qualified name of the initializer class and the assembly it's in. (當您不想讓 EF 使用初始化運算式時,可以在 context 元素上設定屬性: disableDatabaseInitialization="true")。如需詳細資訊,請參閱設定檔案設定(When you don't want EF to use the initializer, you can set an attribute on the context element: disableDatabaseInitialization="true".) For more information, see Configuration File Settings.

    web.config檔案中設定初始化運算式的替代方法是,藉由將 Database.SetInitializer 語句加入至Global.asax.cs檔案中的 Application_Start 方法,在程式碼中執行此動作。An alternative to setting the initializer in the Web.config file is to do it in code by adding a Database.SetInitializer statement to the Application_Start method in the Global.asax.cs file. 如需詳細資訊,請參閱瞭解 Entity Framework Code First 中的資料庫初始化運算式For more information, see Understanding Database Initializers in Entity Framework Code First.

應用程式現在已設定,因此當您第一次在指定的應用程式執行中存取資料庫時,Entity Framework 會將資料庫與模型(您的 SchoolContext 和實體類別)做比較。The application is now set up so that when you access the database for the first time in a given run of the application, Entity Framework compares the database to the model (your SchoolContext and entity classes). 如果有差異,應用程式會卸載並重新建立資料庫。If there's a difference, the application drops and re-creates the database.

Note

當您將應用程式部署到生產 web 伺服器時,您必須移除或停用卸載並重新建立資料庫的程式碼。When you deploy an application to a production web server, you must remove or disable code that drops and re-creates the database. 您將在本系列稍後的教學課程中執行此動作。You'll do that in a later tutorial in this series.

設定 EF 6 使用 LocalDBSet up EF 6 to use LocalDB

LocalDB是輕量版的 SQL Server Express 資料庫引擎。LocalDB is a lightweight version of the SQL Server Express database engine. 安裝和設定、視需要啟動,以及在使用者模式中執行,都很容易。It's easy to install and configure, starts on demand, and runs in user mode. LocalDB 會在 SQL Server Express 的特殊執行模式下執行,可讓您使用資料庫做為 .mdf檔案。LocalDB runs in a special execution mode of SQL Server Express that enables you to work with databases as .mdf files. 如果您想要能夠使用專案來複製資料庫,您可以將 LocalDB 資料庫檔案放在 Web 專案的應用程式_Data資料夾中。You can put LocalDB database files in the App_Data folder of a web project if you want to be able to copy the database with the project. SQL Server Express 中的使用者實例功能也可讓您使用 .mdf檔案,但是使用者實例功能已被取代;因此,建議使用 LocalDB 來處理 .mdf檔案。The user instance feature in SQL Server Express also enables you to work with .mdf files, but the user instance feature is deprecated; therefore, LocalDB is recommended for working with .mdf files. LocalDB 預設會隨 Visual Studio 安裝。LocalDB is installed by default with Visual Studio.

通常,SQL Server Express 不會用於生產 web 應用程式。Typically, SQL Server Express is not used for production web applications. 不建議將 LocalDB 用於與 web 應用程式搭配使用的生產環境,因為它不是設計用於 IIS。LocalDB in particular is not recommended for production use with a web application because it's not designed to work with IIS.

  • 在本教學課程中,您將使用 LocalDB。In this tutorial, you'll work with LocalDB. 開啟應用程式的 web.config 檔案,然後在 appSettings 元素前面加入 connectionStrings 元素,如下列範例所示。Open the application Web.config file and add a connectionStrings element preceding the appSettings element, as shown in the following example. (請務必更新根專案資料夾中的 web.config 檔案。(Make sure you update the Web.config file in the root project folder. Views子資料夾中也有一個 web.config檔案,您不需要更新此檔案)。There's also a Web.config file in the Views subfolder that you don't need to update.)

    <connectionStrings>
        <add name="SchoolContext" connectionString="Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=ContosoUniversity1;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
    </connectionStrings>
    <appSettings>
      <add key="webpages:Version" value="3.0.0.0" />
      <add key="webpages:Enabled" value="false" />
      <add key="ClientValidationEnabled" value="true" />
      <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    </appSettings>
    

您已新增的連接字串會指定 Entity Framework 將使用名為ContosoUniversity1的 LocalDB 資料庫。The connection string you've added specifies that Entity Framework will use a LocalDB database named ContosoUniversity1.mdf. (資料庫尚不存在,但 EF 會加以建立)。如果您想要在應用程式_Data資料夾中建立資料庫,您可以將 AttachDBFilename=|DataDirectory|\ContosoUniversity1.mdf 新增至連接字串。(The database doesn't exist yet but EF will create it.) If you want to create the database in your App_Data folder, you could add AttachDBFilename=|DataDirectory|\ContosoUniversity1.mdf to the connection string. 如需連接字串的詳細資訊,請參閱SQL Server ASP.NET Web 應用程式的連接字串For more information about connection strings, see SQL Server Connection Strings for ASP.NET Web Applications.

您實際上不需要在 web.config 檔案中使用連接字串。You don't actually need a connection string in the Web.config file. 如果您未提供連接字串,Entity Framework 會根據您的內容類別來使用預設連接字串。If you don't supply a connection string, Entity Framework uses a default connection string based on your context class. 如需詳細資訊,請參閱Code First 至新的資料庫For more information, see Code First to a New Database.

建立控制器和檢視Create controller and views

現在您將建立網頁來顯示資料。Now you'll create a web page to display data. 要求資料的程式會自動觸發資料庫的建立。The process of requesting the data automatically triggers the creation of the database. 首先您要建立新的控制器。You'll begin by creating a new controller. 但是在執行此動作之前,請先建立專案,讓模型和內容類別別可用於 MVC 控制器的架構。But before you do that, build the project to make the model and context classes available to MVC controller scaffolding.

  1. 以滑鼠右鍵按一下方案總管中的 [控制器] 資料夾,選取 [加入],然後按一下 [新增 scaffold 專案]。Right-click the Controllers folder in Solution Explorer, select Add, and then click New Scaffolded Item.

  2. 在 [新增 Scaffold ] 對話方塊中,使用 [Entity Framework] 選取 [具有視圖的 MVC 5 控制器],然後選擇 [新增]。In the Add Scaffold dialog box, select MVC 5 Controller with views, using Entity Framework, and then choose Add.

    Visual Studio 中的 [新增 Scaffold] 對話方塊

  3. 在 [新增控制器] 對話方塊中,進行下列選擇,然後選擇 [新增]:In the Add Controller dialog box, make the following selections, and then choose Add:

    • 模型類別: Student (ContosoUniversity)Model class: Student (ContosoUniversity.Models). (如果您在下拉式清單中看不到這個選項,請建立專案,然後再試一次)。(If you don't see this option in the drop-down list, build the project and try again.)

    • 資料內容類別: SchoolCoNtext (ContosoUniversity)Data context class: SchoolContext (ContosoUniversity.DAL).

    • 控制器名稱: StudentController (不是 studentscontroller.cs)。Controller name: StudentController (not StudentsController).

    • 保留其他欄位的預設值。Leave the default values for the other fields.

      當您按一下 [新增] 時,scaffolder 會建立一個StudentController.cs檔,以及一組可與控制器搭配使用的視圖( . cshtml檔案)。When you click Add, the scaffolder creates a StudentController.cs file and a set of views (.cshtml files) that work with the controller. 在未來建立使用 Entity Framework 的專案時,您也可以利用 scaffolder 的一些額外功能:建立您的第一個模型類別、不要建立連接字串,然後在 [新增控制器] 方塊中選取 [資料內容類別] 旁邊的 [ + ] 按鈕,以指定新的資料內容In the future when you create projects that use Entity Framework, you can also take advantage of some additional functionality of the scaffolder: create your first model class, don't create a connection string, and then in the Add Controller box specify New data context by selecting the + button next to Data context class. Scaffolder 會建立您的 DbContext 類別和您的連接字串,以及控制器和 views。The scaffolder will create your DbContext class and your connection string as well as the controller and views.

  4. Visual Studio 會開啟Controllers\StudentController.cs檔案。Visual Studio opens the Controllers\StudentController.cs file. 您會看到已建立可具現化資料庫內容物件的類別變數:You see that a class variable has been created that instantiates a database context object:

    private SchoolContext db = new SchoolContext();
    

    Index 動作方法會藉由讀取資料庫內容實例的 Students 屬性,從學生實體集取得學生的清單:The Index action method gets a list of students from the Students entity set by reading the Students property of the database context instance:

    public ViewResult Index()
    {
        return View(db.Students.ToList());
    }
    

    Student\Index.cshtml view 會在資料表中顯示此清單:The Student\Index.cshtml view displays this list in a table:

    <table>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.LastName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.FirstMidName)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.EnrollmentDate)
            </th>
            <th></th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.LastName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.FirstMidName)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EnrollmentDate)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
                @Html.ActionLink("Details", "Details", new { id=item.ID }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.ID })
            </td>
        </tr>
    }
    
  5. 按 Ctrl+F5 執行專案。Press Ctrl+F5 to run the project. (如果您收到「無法建立陰影複製」錯誤,請關閉瀏覽器,然後再試一次)。(If you get a "Cannot create Shadow Copy" error, close the browser and try again.)

    按一下 [學生] 索引標籤,查看 Seed 方法所插入的測試資料。Click the Students tab to see the test data that the Seed method inserted. 視瀏覽器視窗的範圍而定,您會在頂端的網址列中看到 [Student] 索引標籤連結,或者您必須按一下右上角才能看到連結。Depending on how narrow your browser window is, you'll see the Student tab link in the top address bar or you'll have to click the upper right corner to see the link.

    功能表按鈕

檢視資料庫View the database

當您執行 [學生] 頁面,而應用程式嘗試存取資料庫時,EF 發現沒有資料庫,而且已建立一個。When you ran the Students page and the application tried to access the database, EF discovered that there was no database and created one. EF 接著會執行種子方法,將資料填入資料庫。EF then ran the seed method to populate the database with data.

您可以使用伺服器總管SQL Server 物件總管(SSOX),在 Visual Studio 中查看資料庫。You can use either Server Explorer or SQL Server Object Explorer (SSOX) to view the database in Visual Studio. 在本教學課程中,您將使用伺服器總管For this tutorial, you'll use Server Explorer.

  1. 關閉瀏覽器。Close the browser.

  2. 伺服器總管中,展開 [資料連線] (您可能需要先選取 [重新整理] 按鈕)、展開 [ School CoNtext (ContosoUniversity) ],然後展開 [資料表] ,以查看新資料庫中的資料表。In Server Explorer, expand Data Connections (you may need to select the refresh button first), expand School Context (ContosoUniversity), and then expand Tables to see the tables in your new database.

  3. 以滑鼠右鍵按一下 [ Student ] 資料表,然後按一下 [顯示資料表資料],以查看已建立的資料行以及已插入資料表中的資料列。Right-click the Student table and click Show Table Data to see the columns that were created and the rows that were inserted into the table.

  4. 關閉伺服器總管連接。Close the Server Explorer connection.

ContosoUniversity1% USERPROFILE% 資料夾中的資料庫檔案。The ContosoUniversity1.mdf and .ldf database files are in the %USERPROFILE% folder.

因為您使用的是 DropCreateDatabaseIfModelChanges 初始化運算式,所以您現在可以變更 Student 類別、再次執行應用程式,而且會自動重新建立資料庫以符合您的變更。Because you're using the DropCreateDatabaseIfModelChanges initializer, you could now make a change to the Student class, run the application again, and the database would automatically be re-created to match your change. 例如,如果您將 EmailAddress 屬性加入 Student 類別,請再次執行 [學生] 頁面,然後再次查看資料表,您會看到新的 EmailAddress 資料行。For example, if you add an EmailAddress property to the Student class, run the Students page again, and then look at the table again, you'll see a new EmailAddress column.

慣例Conventions

為了讓 Entity Framework 能夠為您建立完整資料庫,您必須撰寫的程式碼數量最少,因為慣例或 Entity Framework 所做的假設。The amount of code you had to write in order for Entity Framework to be able to create a complete database for you is minimal because of conventions, or assumptions that Entity Framework makes. 其中有些是已記下或已使用,而不需要您知道它們:Some of them have already been noted or were used without your being aware of them:

  • 實體類別名稱的複數化形式會當做資料表名稱使用。The pluralized forms of entity class names are used as table names.
  • 實體屬性名稱會用於資料行名稱。Entity property names are used for column names.
  • 名為 IDclassname ID 的實體屬性會被辨識為主鍵屬性。Entity properties that are named ID or classname ID are recognized as primary key properties.
  • 如果將屬性命名為 <導覽屬性名稱><主鍵屬性名稱> (例如 StudentID Student 實體的主要索引鍵 Student),則會將其視為外鍵屬性。IDA property is interpreted as a foreign key property if it's named <navigation property name><primary key property name> (for example, StudentID for the Student navigation property since the Student entity's primary key is ID). 外鍵屬性也可以命名為相同 <主鍵屬性名稱> (例如 EnrollmentID,因為 Enrollment 實體的主要索引鍵是 EnrollmentID)。Foreign key properties can also be named the same simply <primary key property name> (for example, EnrollmentID since the Enrollment entity's primary key is EnrollmentID).

您已瞭解可以覆寫慣例。You've seen that conventions can be overridden. 例如,您指定不應複數化資料表名稱,稍後您會看到如何將屬性明確地標示為外鍵屬性。For example, you specified that table names shouldn't be pluralized, and you'll see later how to explicitly mark a property as a foreign key property.

取得程式碼Get the code

下載已完成的專案Download Completed Project

其他資源Additional resources

如需 EF 6 的詳細資訊,請參閱下列文章:For more about EF 6, see these articles:

後續步驟Next steps

在本教學課程中,您已:In this tutorial, you:

  • 建立 MVC web 應用程式Created an MVC web app
  • 設定網站樣式Set up the site style
  • 已安裝 Entity Framework 6Installed Entity Framework 6
  • 建立資料模型Created the data model
  • 建立資料庫內容Created the database context
  • 使用測試資料將 DB 初始化Initialized DB with test data
  • 設定 EF 6 使用 LocalDBSet up EF 6 to use LocalDB
  • 建立控制器和檢視Created controller and views
  • 檢視資料庫Viewed the database

前往下一篇文章,以瞭解如何在您的控制器和 views 中檢查和自訂建立、讀取、更新、刪除(CRUD)程式碼。Advance to the next article to learn how to review and customize the create, read, update, delete (CRUD) code in your controllers and views.