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

注意

对于新的开发,我们建议 ASP.NET Core Razor Pages over ASP.NET MVC 控制器和视图。 有关与使用 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 运行网站。 会看到包含“main”菜单的主页。

安装 Entity Framework 6

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

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

    Install-Package EntityFramework
    

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

创建数据模型

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

课程<->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 将名为 IDclassnameID 的属性解释为主键。

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

导航属性通常定义为 virtual ,以便它们可以利用某些实体框架功能,例如 延迟加载。 稍后将在本系列后面的 阅读相关数据 教程中介绍 (延迟加载。)

如果导航属性可以具有多个实体 (如多对多或一对多关系),那么导航属性的类型必须是可以添加、 删除和更新条目的容器,如 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 without classname 来更轻松地在数据模型中实现继承。

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

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

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

实体框架将属性解释为外键属性(如果命名<的导航属性名称><主键属性名称> (,例如,对于Student导航属性,StudentID因为Student实体的主键是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 特性的例子。 简单来说,此特性让你能自行指定主键,而不是让数据库自动指定主键。

创建数据库上下文

协调给定数据模型的实体框架功能的main类是数据库上下文类。 通过派生自 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 因为实体引用实体, EnrollmentEnrollment 实体引用实体 Course

指定连接字符串

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

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

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

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

指定单一表名称

modelBuilder.Conventions.RemoveOnModelCreating 方法中的 语句阻止对表名进行复数化。 如果不这样做,数据库中生成的表将命名为 StudentsCoursesEnrollments。 相反,表名称将为 StudentCourseEnrollment。 开发者对表名称是否应为复数意见不一。 本教程使用单数形式,但重要的是,你可以通过包括或省略此代码行来选择你喜欢的窗体。

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

在应用程序运行时,实体框架可以自动创建 (或删除并重新创建) 数据库。 可以指定每次应用程序运行时或仅在模型与现有数据库不同步时执行此操作。 还可以编写 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 文件中设置初始值设定项的另一种方法 Database.SetInitializer 是在代码中执行此操作,方法是将 语句添加到 Application_StartGlobal.asax.cs 文件中的 方法。 有关详细信息,请参阅 了解 Entity Framework Code First 中的数据库初始值设定项

现在已设置应用程序,以便在给定运行的应用程序中首次访问数据库时,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文件,并在 元素前面appSettings添加元素connectionStrings,如以下示例所示。 (请确保更新根项目文件夹中的 Web.config 文件。“视图”子文件夹中还有一个无需更新的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>
    

添加的连接字符串指定实体框架将使用名为 ContosoUniversity1.mdf 的 LocalDB 数据库。 (数据库尚不存在,但 EF 将创建它。) 如果要在 App_Data 文件夹中创建数据库,可以添加到 AttachDBFilename=|DataDirectory|\ContosoUniversity1.mdf 连接字符串。 有关连接字符串的详细信息,请参阅 SQL Server ASP.NET Web 应用程序的连接字符串

实际上不需要 Web.config 文件中的连接字符串。 如果不提供连接字符串,Entity Framework 会根据上下文类使用默认连接字符串。 有关详细信息,请参阅 Code First to a New Database

创建控制器和视图

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

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

  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 列。

约定

由于实体框架做出的 约定或假设,为使实体框架能够为你创建完整数据库而必须编写的代码量很少。 其中一些已在你不知道的情况下被注意到或使用:

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

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

获取代码

下载已完成项目

其他资源

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

后续步骤

在本教程中,你将了解:

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

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