教程:开始使用 MVC 5 的 Entity Framework 6 Code First

注意

对于新开发,我们建议 ASP.NET ASP.NET MVC 控制器和视图的 Core Razor Pages 。 有关与使用 Razor Pages 类似的教程系列,请参阅 教程:ASP.NET Core 中的 Razor Pages 入门。 新教程:

  • 易于关注。
  • 提供更多 EF Core 最佳做法。
  • 使用更高效的查询。
  • 通过最新 API 更新到更高版本。
  • 涵盖更多功能。
  • 是开发新应用程序的首选方法。

本系列教程介绍如何生成使用 Entity Framework 6 进行数据访问的 ASP.NET MVC 5 应用程序。 本教程使用 Code First 工作流。 有关如何在 Code First、Database First 和 Model First 之间进行选择的信息,请参阅 “创建模型”。

本教程系列介绍如何生成 Contoso University 示例应用程序。 示例应用程序是一个简单的大学网站。 使用它,可以查看和更新学生、课程和讲师信息。 下面是你创建的两个屏幕:

Students_Index_page

编辑学生

在本教程中,你将了解:

  • 创建 MVC Web 应用
  • 设置网站样式
  • 安装 Entity Framework 6
  • 创建数据模型
  • 创建数据库上下文
  • 使用测试数据初始化数据库
  • 设置 EF 6 以使用 LocalDB
  • 创建控制器和视图
  • 查看数据库

先决条件

创建 MVC Web 应用

  1. 打开 Visual Studio 并使用 ASP.NET Web 应用程序 (.NET Framework) 模板创建 C# Web 项目。 将项目 命名为 ContosoUniversity ,然后选择“ 确定”。

    Visual Studio 中的“新建项目”对话框

  2. “新建 ASP.NET Web 应用程序 - ContosoUniversity 中,选择 MVC

    Visual Studio 中的“新建 Web 应用”对话框

    注意

    默认情况下, “身份验证 ”选项设置为 “无身份验证”。 在本教程中,Web 应用不需要用户登录。 此外,它不会根据登录者限制访问。

  3. 选择“确定”以创建项目。

设置网站样式

通过几个简单的更改设置站点菜单、 布局和主页。

  1. 打开 Views\Shared\_Layout.cshtml,并进行以下更改:

    • 将“我的 ASP.NET 应用程序”和“应用程序名称”的每个匹配项更改为“Contoso University”。
    • 为学生、课程、讲师和部门添加菜单条目,并删除“联系人”条目。

    以下代码片段中突出显示了这些更改:

    <!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 的文本替换为有关此应用程序的文本:

    @{
        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 运行网站。 你会看到主菜单的主页。

安装 Entity Framework 6

  1. “工具”菜单中,选择“NuGet 程序包管理器”,然后选择“程序包管理器控制台”。

  2. 在“程序包管理器控制台”窗口中,输入以下命令:

    Install-Package EntityFramework
    

此步骤是本教程手动执行的几个步骤之一,但可以通过 ASP.NET MVC 基架功能自动完成此步骤。 你正在手动执行这些操作,以便查看使用 Entity Framework(EF)所需的步骤。 稍后将使用基架创建 MVC 控制器和视图。 另一种方法是让基架自动安装 EF NuGet 包、创建数据库上下文类和创建连接字符串。 准备好以这种方式执行此操作时,只需跳过这些步骤,并在创建实体类后搭建 MVC 控制器基架。

创建数据模型

接下来你将创建 Contoso 大学应用程序的实体类。 你将从以下三个实体开始:

Course-Enrollment-Student<><>

实体 关系
注册课程 一对多
学生注册 一对多

StudentEnrollment实体之间是一对多的关系,CourseEnrollment 实体之间也是一个对多的关系。 换而言之,一名学生可以修读任意数量的课程, 并且某一课程可以被任意数量的学生修读。

在以下部分中,你将为其中每个实体创建一个类。

注意

如果在创建完所有这些实体类之前尝试编译项目,则会收到编译器错误。

Student 实体

  • Models 文件夹中,右键单击解决方案资源管理器中的文件夹并选择“添加>”,创建名为Student.cs类文件。 将模板代码替换为以下代码:

    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 属性将成为对应于此类的数据库表中的主键。 默认情况下,Entity Framework 将命名ID类名ID的属性解释为主键。

Enrollments 属性是导航属性。 导航属性中包含与此实体相关的其他实体。 在这种情况下,Enrollments实体的属性Student将包含与该Student实体相关的所有Enrollment实体。 换句话说,如果数据库中的给定 Student 行具有两个相关 Enrollment 行(在其 StudentID 外键列中包含该学生的主键值的行),该 Student 实体的 Enrollments 导航属性将包含这两 Enrollment 个实体。

导航属性通常被定义为 virtual 可以利用某些 Entity Framework 功能,例如 延迟加载。 (延迟加载将在稍后解释,在 阅读本系列后面的相关数据 教程。

如果导航属性可以具有多个实体 (如多对多或一对多关系),那么导航属性的类型必须是可以添加、 删除和更新条目的容器,如 ICollection

Enrollment 实体

  • Models 文件夹中,创建 Enrollment.cs 并且用以下代码替换现有代码:

    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属性将是主键;此实体使用类名ID模式,而不是ID在实体中看到Student的单独模式。 通常情况下,你选择一个主键模式,并在你的数据模型自始至终使用这种模式。 在这里,使用了两种不同的模式只是为了说明你可以使用任一模式来指定主键。 在后面的教程中,你将了解如何使用 ID ,而无需 classname 更轻松地在数据模型中实现继承。

Grade属性是枚举Grade 声明类型后的`?`表示 Grade 属性可以为 null。 null 的等级与零年级不同, null 表示成绩未知或尚未分配。

StudentID 属性是一个外键,Student 是与其且对应的导航属性。 Enrollment 实体与一个 Student 实体相关联,因此该属性只包含单个 Student 实体 (与前面所看到的 Student.Enrollments 导航属性不同后,`Student`中可以容纳多个 Enrollment 实体)。

CourseID 属性是一个外键, Course 是与其对应的导航属性。 Enrollment 实体与一个 Course 实体相关联。

Entity Framework 将属性解释为外键属性(如果属性名称为<导航属性名称><主键属性名称>(例如,StudentID因为StudentStudent实体的主键为导航属性)。ID 外键属性也可以命名为相同的主<键属性名称>(例如,CourseID因为Course实体的主键为 CourseID)。

Course 实体

  • Models 文件夹中,创建 Course.cs,将模板代码替换为以下代码:

    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 属性是导航属性。 一个 Course 体可以与任意数量的 Enrollment 实体相关。

在本系列的后续教程中,我们将详细介绍 DatabaseGeneratedAttribute 该属性。 简单来说,此特性让你能自行指定主键,而不是让数据库自动指定主键。

创建数据库上下文

协调给定数据模型的 Entity Framework 功能的主类是 数据库上下文 类。 通过派生自 System.Data.Entity.DbContext 类来创建此类。 在代码中,指定数据模型中包括哪些实体。 你还可以定义某些 Entity Framework 行为。 在此项目中将数据库上下文类命名为 SchoolContext

  • 若要在 ContosoUniversity 项目中创建文件夹,请右键单击解决方案资源管理器中的项目,然后单击“添加,然后单击“新建文件夹”。 为新文件夹 DAL 命名(对于数据访问层)。 在该文件夹中,创建一个名为 SchoolContext.cs的新类文件,并将模板代码替换为以下代码:

    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>();
            }
        }
    }
    

指定实体集

此代码为每个实体集创建一个 DbSet 属性。 在 Entity Framework 术语中,实体集通常对应于数据库表,实体对应于表中的行。

注意

可以省略 DbSet<Enrollment>DbSet<Course> 语句,它的工作方式相同。 实体框架会隐式包含它们, Student 因为实体引用 Enrollment 实体,而 Enrollment 实体引用 Course 实体。

指定连接字符串

连接字符串的名称(稍后将添加到 Web.config 文件)传递给构造函数。

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

还可以传入连接字符串本身,而不是存储在 Web.config 文件中的名称。 有关指定要使用的数据库的选项的详细信息,请参阅 连接字符串和模型

如果未显式指定连接字符串或名称,Entity Framework 假定连接字符串名称与类名相同。 然后,此示例中的默认连接字符串名称与SchoolContext显式指定的名称相同。

指定单一表名称

modelBuilder.Conventions.Remove OnModelCreating 方法中的语句可防止表名被复数化。 如果未执行此操作,数据库中生成的表将命名 StudentsCourses并且 Enrollments。 相反,表名将是 StudentCourse并且 Enrollment。 开发者对表名称是否应为复数意见不一。 本教程使用单一窗体,但要点是,可以通过包括或省略此代码行来选择你喜欢的表单。

使用测试数据初始化数据库

实体框架可以在应用程序运行时自动创建数据库(或删除并重新创建)。 可以指定每次应用程序运行时或仅当模型与现有数据库不同步时,都应执行此操作。 还可以编写 Seed Entity Framework 在创建数据库后自动调用的方法,以便使用测试数据填充它。

默认行为是仅当数据库不存在(如果模型已更改且数据库已存在时引发异常)。 在本部分中,你将指定每当模型发生更改时,都应删除并重新创建数据库。 删除数据库会导致所有数据丢失。 这在开发过程中通常没问题,因为在 Seed 重新创建数据库并重新创建测试数据时,该方法将运行。 但在生产环境中,每次需要更改数据库架构时,通常都不希望丢失所有数据。 稍后你将了解如何使用Code First 迁移更改数据库架构来处理模型更改,而不是删除和重新创建数据库。

  1. 在 DAL 文件夹中,创建名为 SchoolInitializer.cs 的新类文件,并将模板代码替换为以下代码,这会导致在需要时创建数据库,并将测试数据加载到新数据库中。

    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 采用数据库上下文对象作为输入参数,该方法中的代码使用该对象向数据库添加新实体。 对于每个实体类型,该代码将创建一组新实体,将它们添加到相应的 DbSet 属性,然后将更改保存到数据库。 在每组实体之后调用该方法并不是必需的 SaveChanges ,但这样做有助于在代码写入数据库时出现异常时找到问题源。

  2. 若要告知 Entity Framework 使用初始值设定项类,请将元素添加到 entityFramework 应用程序 Web.config 文件中的元素(根项目文件夹中的元素),如以下示例所示:

    <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 指定初始值设定项类的完全限定名及其所在其中的程序集。 (如果不希望 EF 使用初始值设定项,可以在元素上 context 设置属性: disableDatabaseInitialization="true".)有关详细信息,请参阅 配置文件设置

    在 Web.config 文件中设置初始值设定项的替代方法是通过在 Global.asax.cs 文件中向方法添加Database.SetInitializer语句Application_Start在代码中执行此操作。 有关详细信息,请参阅 首先了解 Entity Framework Code 中的数据库初始值设定项。

应用程序现在已设置,以便在给定运行应用程序时首次访问数据库时,Entity Framework 会将数据库与模型(你的 SchoolContext 和实体类)进行比较。 如果存在差异,应用程序会删除并重新创建数据库。

注意

将应用程序部署到生产 Web 服务器时,必须删除或禁用删除并重新创建数据库的代码。 在本系列的后续教程中,你将执行此操作。

设置 EF 6 以使用 LocalDB

LocalDB 是 SQL Server Express 数据库引擎的轻型版本。 可以轻松安装和配置、按需启动并在用户模式下运行。 LocalDB 以 SQL Server Express 的特殊执行模式运行,使你可以将数据库用作 .mdf 文件。 如果要使用项目复制数据库,可以将 LocalDB 数据库文件 放在 Web 项目的App_Data 文件夹中。 SQL Server Express 中的用户实例功能还可用于处理 .mdf 文件,但用户实例功能已弃用;因此,建议使用 LocalDB 来处理 .mdf 文件。 LocalDB 默认随 Visual Studio 一起安装。

通常,SQL Server Express 不用于生产 Web 应用程序。 特别是不建议将 LocalDB 用于 Web 应用程序,因为它不设计用于 IIS。

  • 在本教程中,你将使用 LocalDB。 打开应用程序 Web.config 文件并添加 connectionStrings 元素前面的 appSettings 元素,如以下示例所示。 (请确保更新根项目文件夹中的 Web.config 文件。Views 子文件夹中还有一个不需要更新的 Web.config 文件

    <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.mdfLocalDB 数据库。 (数据库尚不存在,但 EF 将创建它。如果要在 App_Data 文件夹中创建数据库,可以添加到AttachDBFilename=|DataDirectory|\ContosoUniversity1.mdf连接字符串。 有关连接字符串的详细信息,请参阅适用于 ASP.NET Web 应用程序的 SQL Server 连接字符串。

Web.config 文件中实际上不需要连接字符串。 如果未提供连接字符串,Entity Framework 会基于上下文类使用默认连接字符串。 有关详细信息,请参阅 Code First 到新数据库

创建控制器和视图

现在,你将创建一个网页来显示数据。 请求数据的过程会自动触发数据库的创建。 首先创建新的控制器。 但在执行此操作之前,请生成项目,使模型和上下文类可用于 MVC 控制器基架。

  1. 右键单击解决方案资源管理器中的“控制器”文件夹,选择“添加,然后单击“新建基架项”。

  2. “添加基架 ”对话框中,选择 具有视图的 MVC 5 控制器,使用实体框架,然后选择“ 添加”。

    Visual Studio 中的“添加基架”对话框

  3. “添加控制器 ”对话框中,进行以下选择,然后选择“ 添加” :

    • 模型类:学生(ContosoUniversity.Models)。 (如果在下拉列表中看不到此选项,请生成项目,然后重试。

    • 数据上下文类:SchoolContext (ContosoUniversity.DAL)。

    • 控制器名称: StudentController (而不是 StudentsController)。

    • 对于其他字段,保留默认值。

      单击“添加时,基架会创建一个StudentController.cs文件和一组可用于控制器的视图(.cshtml 文件)。 在将来创建使用 Entity Framework 的项目时,还可以利用基架的某些附加功能:创建第一个模型类,不要创建连接字符串,然后在“添加控制器”框中通过选择+数据上下文类旁边的按钮来指定新数据上下文。 基架将创建类DbContext和连接字符串以及控制器和视图。

  4. Visual Studio 将 打开 Controllers\StudentController.cs 文件。 你会看到已创建类变量来实例化数据库上下文对象:

    private SchoolContext db = new SchoolContext();
    

    操作Index方法通过读取Students数据库上下文实例的属性从 Students 实体获取学生列表:

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

    Student \Index.cshtml 视图在表中显示此列表:

    <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 运行项目。 (如果收到“无法创建卷影复制”错误,请关闭浏览器,然后重试。

    单击“学生”选项卡,查看方法插入的测试数据Seed。 根据浏览器窗口的窄程度,你将在顶部地址栏中看到“学生”选项卡链接,或者必须单击右上角才能看到该链接。

    “菜单”按钮

查看数据库

运行“学生”页和应用程序尝试访问数据库时,EF 发现没有数据库并创建了一个数据库。 然后,EF 运行种子方法以使用数据填充数据库。

可以使用服务器资源管理器SQL Server 对象资源管理器 (SSOX) 在 Visual Studio 中查看数据库。 在本教程中,你将使用 服务器资源管理器

  1. 关闭浏览器。

  2. 服务器资源管理器中,展开 “数据连接 ”(可能需要先选择刷新按钮)、展开 “学校上下文”(ContosoUniversity),然后展开 “表 ”以查看新数据库中的表。

  3. 右键单击“学生”表,然后单击“显示表数据以查看已创建的列以及插入表中的行。

  4. 关闭服务器资源管理器连接。

ContosoUniversity1.mdf.ldf 数据库文件位于 %USERPROFILE% 文件夹中。

由于使用的是 DropCreateDatabaseIfModelChanges 初始值设定项,因此现在可以对 Student 类进行更改,再次运行应用程序,并自动重新创建数据库以匹配更改。 例如,如果将属性 EmailAddress 添加到 Student 课堂,请再次运行“学生”页,然后再次查看该表,你将看到一个新 EmailAddress 列。

约定

为了实体框架能够为你创建完整的数据库,必须编写的代码量非常少,因为 约定或 Entity Framework 做出的假设。 其中一些已记录或已使用,但不知道它们:

  • 实体类名称的复数形式用作表名。
  • 使用实体属性名作为列名。
  • 命名ID类名ID的实体属性被识别为主键属性。
  • 如果属性名为 <导航属性名><主键属性名>(例如,StudentID 对应 Student 导航属性,因为 Student 实体的主键是 ID),则其将被解释为外键属性。 外键属性也可以命名为相同的主 <键属性名称> (例如, EnrollmentID 因为 Enrollment 实体的主键为 EnrollmentID)。

你已看到可以重写约定。 例如,你指定了不应对表名称进行复数化,稍后将介绍如何将属性显式标记为外键属性。

获取代码

下载已完成的项目

其他资源

有关 EF 6 的详细信息,请参阅以下文章:

后续步骤

本教程介绍以下操作:

  • 创建了 MVC Web 应用
  • 设置网站样式
  • 已安装的实体框架 6
  • 已创建数据模型
  • 已创建数据库上下文
  • 已使用测试数据初始化数据库
  • 设置 EF 6 以使用 LocalDB
  • 已创建控制器和视图
  • 已查看数据库

转到下一篇文章,了解如何查看和自定义控制器和视图中的创建、读取、更新、删除(CRUD)代码。