五、模型

数据是每个应用的核心。 用户在应用中输入数据,编辑输入的数据,并搜索数据。 我们甚至可以说,我们构建的应用只是我们对应用数据执行操作的接口。 因此,任何框架都必须提供一种机制来更容易和更易于管理地处理数据操作。 模型在 ASP.NET MVC 用于表示业务域数据。

在本章中,你将学习以下主题:

  • 模型及其目的
  • 创建一个简单的模型并在控制器和视图中使用它。 净 MVC 应用
  • 创建一个特定于 View 模型的模型
  • ASP 中的数据流.NET MVC 应用中的模型与ViewModels
  • 实体框架的目的及其特性和好处
  • 使用实体框架添加、更新和删除数据
  • 在 ASP 中使用实体框架。 净 MVC 应用

型号

模型是简单的POCO(普通的旧 c#对象)类,代表您的业务领域数据。 对于电子商务企业,模型类将是ProductOrderInventory。 如果你正在创建一个大学申请,典型课程将是StudentTeacher,Subject。 模型表示应用中的业务领域数据,它们不知道应用中使用的底层数据库。 事实上,您甚至不需要数据库来处理模型。

它们可以表示存储在 XML 文件或 CSV 文件或应用中的任何其他数据中的数据。 话虽如此,这些模型可以用于与数据库交互(在大多数情况下),但它们与数据库没有任何依赖关系。

下面的步骤描述了如何创建一个 ASP.NET Core 应用,使用模型:

  1. 确保创建一个 ASP.NET 5 应用与一个空模板。 安装 ASP.NET CoreNuGet包并配置它,就像前面一章中讨论的那样。
  2. 创建一个Controllers文件夹,并使用单个Index操作方法创建一个HomeController
  3. Views模型创建以下文件夹/文件:
    • Views:此文件夹在您的项目中。
    • Views\_ViewStart.cshtml:标识Layout文件的名称。
    • Views\Shared文件夹:此文件夹保存了应用的所有共享视图组件。
    • Shared\_Layout.cshtml:该文件确定了您的 web 应用结构应该是什么样子。
    • Views\Home文件夹:此文件夹包含您HomeController的所有视图。
    • Views\Home\Index.cshtml:此视图对应HomeControllerIndex动作方法。

现在,我们已经创建了一个 ASP。 带有控制器和视图的 NET Core 应用。

让我们在应用中创建一个Models文件夹; 这个文件夹将包含所有的模型文件。 在真实的应用中,这个文件夹和各自的模型文件将驻留在不同的项目中。 为了简单起见,我们将Models文件夹及其文件保存在同一个项目中。

Models

让我们在Models文件夹中创建一个简单的模型类Product模型:

public class Product { 
  public int ProductId { get; set; } 
  public string Name { get; set; } 
  public decimal Price { get; set; } 
} 

这个Product模型类与其他 c#类没有什么不同,它包含了一些关于产品的属性。

更新HomeController中的Index操作方法以使用Product模型,如下面的代码片段所示。 我们正在构建模型数据并将模型数据传递给视图,以便它可以显示给用户。 然而,而不是建议在控制器的操作方法中构建 Model 数据,因为它违反了关注点分离。 为了简单起见,我们在操作方法中构建模型数据。

public IActionResult Index() { 
  /* Build the products model. It is NOT RECOMMENDED to build    models in Controller action methods  like this. In real world appication, these models and the    respective Data Access Layer(DAL) would  be in separate projects. We are creating it here to make things    simpler to explain */ 
  List<Product> Products = new List<Product> { 
    new Product { 
      Name = "Mobile Phone", 
      Price = 300 
    }, 
    new Product { 
      Name = "Laptop", 
      Price = 1000 
    }, 
    new Product { 
      Name = "Tablet", 
      Price = 600 
    } 
  }; 
  return View(Products); 
} 

更新相应的IndexView 方法,使用 Model 数据循环遍历每个产品,并将其显示为无序列表项。 第一行中的@model表示 Model 元数据; 传递给视图的数据类型。 for…each循环中的 Model 表示实际的数据本身,在我们的例子中是一个产品列表:

@model List<Chapter5.Models.Product> 

<ul> 
  @foreach (var Product in Model) { 
    <li>@Product.Name</li> 
  } 
</ul> 

当你运行应用时,你会得到以下输出:

Models

我们已经成功地创建了一个模型,并在控制器和视图中使用了它。

让我们创建一个比较复杂的 Model 类Order(Models文件夹中的Order.cs),它包含产品列表及其总量:

public class Order { 
  public int OrderId { get; set; } 
  public List<Product> Products { get; set; } 
  public decimal Total { get; set; } 
} 

Models

现在,我们必须更新Index动作方法来使用Order模型。 一旦我们构建了产品列表,我们就将产品列表分配给Order属性并计算订单的总成本。 这些计算通常作为业务层的一部分进行。 同样,为了简单起见,我们在操作中构建数据模型和计算; 在实际应用中不应该出现这种情况。

粗体突出显示的代码是我们在 action 方法中所做的更改:

public IActionResult Index() { 
  /* Build the products model. It is NOT RECOMMENDED to build    models in Controller action methods  like this. In real world appication, these models and the    respective Data Access Layer(DAL) would  be in separate projects. We are creating it here to make things    simpler to explain   */ 
  List<Product> Products = new List<Product> { 
    new Product { 
      Name = "Mobile Phone", 
      Price = 300 
    }, 
    new Product { 
      Name = "Laptop", 
      Price = 1000 
    }, 
    new Product { 
      Name = "Tablet", 
      Price = 600 
    } 
  }; 

 Order order = new Order(); 
  order.Products = Products; 
  order.Total = Products.Sum(product => product.Price); 

  return View(order);

} 

视图被更新以适应模型的更改。 模型元数据(@model)被更改,以表明 Order 信息被传递给 View,而不是产品列表。

然后,我们以表格格式显示产品列表。 请注意,所有的模型数据(在本例中是Order对象及其属性)都可以通过模型访问。 例如,Products类可以通过Model.Products访问,Total的值可以通过Model.Total获得:

@model Chapter5.Models.Order 

<table border="1"> 

  <tr> 
    <th>Product Name</th> 
    <th>Price</th> 
  </tr> 

  @foreach (var Product in Model.Products){ 
    <tr> 
      <td>@Product.Name</td> 
      <td>@Product.Price</td> 
    </tr> 
  } 
  <tr> 
    <td><b>Total</b></td> 
    <td><b>@Model.Total</b></td> 
  </tr> 
</table> 

当你运行应用时,你会看到以下输出:

Models

特定于 View 组件的模型

在某些情况下,您可能希望只更新大型模型中的一些属性,或者您可能希望基于一些模型创建一个新模型。 在这种情况下,最好创建一个特定于视图的新模型。

例如,让我们假设我们正在构建一个屏幕,您可以在其中更新产品的价格。 这个简单的屏幕可能只包含三个属性——产品 ID、产品名称和产品价格。 但是产品的 Model 可能包含 30 多个属性来保存产品的所有细节,比如制造商、颜色、大小和其他属性。 我们不需要发送包含所有属性的完整模型,而是可以创建一个新的模型,这个模型只包含几个属性——id、Name 和 Price。

ViewModels 的注意事项

ViewModels 是当你更新模型时,你的视图会自动更新的实体,反之亦然。 在许多在线文章中,甚至在一些书中,他们提到了ViewModels,而实际上他们试图指的是特定于 View的模型。

在 ViewModels 中,绑定有两种方式—当您更新模型或视图时,另一个将自动更新。 让我们考虑一个简单的例子; 表单的左侧有多个字段,右侧有打印预览。 在这种情况下,您在表单中实时输入的任何内容都将立即反映在右侧。 在这种情况下,您可以在键入时使用纯视图模型,您的 ViewModel 将被更新,而ViewModel将在右侧打印预览中被使用。 这些纯 viewmodel 被用于高级 JavaScript 框架中,如KnockoutAngularJS

特定于视图的模型中,我们只以一种方式从模型绑定到视图。 这里,我们将特定于模型的模型发送到视图,而不是通用的模型(它表示一个业务领域类)。

然而,在本书中,为了简洁起见,我们将把针对视图的模型称为ViewModel。 除非另有说明,否则应将所有 ViewModels 读为视图特定的模型。 所以,我犯了和其他作者一样的错误Note on ViewModels

与模型相关的数据流

下面的框图显示了 ASP 中的数据流.NET MVC 应用:

Data flow with respect to a Model

数据源表示应用数据。 应用数据可以驻留在任何地方——从成熟的 RDBMS(如 SQL 服务器)到简单的 Excel 电子表格,或者介于两者之间的任何东西。

模型模型表示应用的业务领域数据,且与所使用的数据源无关。 相同的模型可以用于不同的数据源。

我们可以使用视图中的模型来获取数据或呈现数据。 但是在某些视图中,您可能不需要模型的所有属性。 因此,我们不是将整个模型发送到视图,而是创建特定于视图的模型,并在视图中使用它们。 这样事情就简单多了。

下面是在 ASP 中存储或检索记录时发生的事件的高级序列.NET Core 使用模型:

  1. 用户在应用中的表单(使用视图创建)中输入数据。 表单中的字段不需要表示完整的模型,因为我们只需要在 model 中使用一些属性。
  2. 输入的数据被传递到模型绑定发生的控制器。 模型绑定是将输入到视图中的数据映射到模型或 ViewModel 的过程。
  3. 如果数据是在 ViewModel 中接收到的,那么我们将把 ViewModel 转换为 Model。
  4. 最后,将 Model 数据存储在数据源中。

到目前为止,我们在应用中一直只处理内存中的数据。 在几乎所有的实际应用中,某种形式的数据库将用于数据存储、访问和检索。 在下一节中,我们将讨论实体框架(Entity Framework, ORM 框架),它使。net 应用中的数据访问变得更简单。

模型绑定

模型绑定是将来自视图的模型数据映射到控制器中动作方法的 ViewModel 参数的过程。

让我们考虑一个简单的表单,它有两个表单字段:NameEmailID。 在表单提交时,这些值将映射到控制器的动作方法的ViewModel对象。 模型绑定负责这种映射。 Model 绑定器在表单字段、查询字符串和请求参数中查找匹配。

在前面的示例中,ModelBinder 可以毫无问题地提取具有这些属性的任何类。

由于下面的Person类包含NameEmailID属性,模型绑定器不会抱怨使用该模型映射表单中输入的值:

public class Person { 
  public string Name { get; set; } 
  public string EmailID { get; set; } 
} 

下面的代码片段展示了如何在 action 方法中使用Person类:

public ActionResult Add(Person p) { 
  return View(); 
} 

实体框架

实体框架是对象关系映射(ORM)框架,它允许开发人员直接处理特定于领域的对象以进行数据访问,而不是处理数据库查询。 这大大降低了应用中数据访问层的代码复杂度。

在讨论实体框架及其特性之前,让我们暂停一下,考虑一下在使用 ADO 时,当我们试图将一些信息保存到数据库时所遵循的步骤.NET:

  1. 构造业务域对象。
  2. 创建到数据库的连接。
  3. 打开连接。
  4. 创建命令对象和命令类型。
  5. 将业务域对象的属性添加到命令对象的参数中。
  6. 执行将数据保存到数据库中的命令。

我们必须按照前面提到的 6 个步骤来执行常见操作,比如将数据保存到数据库中。

如果你正在使用一个 ORM 框架,比如实体框架,你只需要三个步骤:

  1. 构造业务域对象。
  2. 为您的业务域对象创建DbContext类。 类的实例表示与数据库的会话。
  3. 使用DBContext类的实例将其保存到数据库中。

你可能想知道这怎么可能。

事实上,在后台,实体框架创建到数据库的连接,并执行查询以将业务域对象保存到数据库中。 为了简单起见,实体框架为您编写所有数据访问代码,以便您可以集中精力实现应用的业务功能,而不是编写数据库层代码。

实体框架是独立于 ASP 的.NET MVC

正如前面所讨论的,实体框架是一个用于访问数据的 ORM 框架,它独立于 ASP。 净 MVC。 实体框架可以在Windows Communication Foundation(WCF)服务、Web API 服务,甚至控制台应用中使用。 您可以在任何类型的应用中使用实体框架,并利用它来使用对象访问数据。 实体框架的概念和功能保持不变,与使用它的应用类型无关。

现在,我们将在控制台应用中使用实体框架。 这使我们能够专注于手头的任务,并演示实体框架的功能,而不是在 ASP 的样板代码上工作.NET Core 应用。 在本章后面的部分中,我们将把实体框架与 ASP 集成在一起.NET Core 应用。

针对 SQL server 的实体框架的最新版本是 7.0.0,在撰写本书时仍处于测试阶段。 EF7 (Entity Framework 7)与之前的版本(Entity Framework 6)相比,带来了显著的变化.NET 5 应用,因此我们将在本书中使用这个版本。

注意事项

我们需要一个数据库来解释实体框架的许多特性。 在继续之前,请在您的 PC 上安装 SQL Server 2014 Express。 安装 SQL Server 2014 Express 和 SQL Server Management Studio 的步骤说明在附录 A 中给出。

使用实体框架创建控制台应用

按照以下步骤创建一个简单的控制台应用:

  1. 选择文件|新项目,选择控制台应用
  2. Name the project and click on OK .

    Creating console applications with the Entity Framework

安装实体框架 7 NuGet 包

在您的应用中安装任何NuGet包有两种方法:

  • 使用NuGet包管理器
  • 使用包管理器控制台

使用 NuGet 包管理器

喜欢图形界面的人可以使用这个选项:

  1. Right-click on the console project and select Manage NuGet Packages from the context menu:

    Using the NuGet Package Manager

  2. Search for EntityFramework.MicrosoftSqlServer in the NuGet package and make sure the Include prerelease checkbox is checked. Click on Install once you select EntityFramework.MicrosoftSqlServer and select Latest pre-release 7.0.0-rc1-final (at the time of writing this book). You can select any latest version of Entity Framework 7:

    Using the NuGet Package Manager

  3. Once you click on Install , the NuGet package manager will ask you to review the changes. Click on OK :

    Using the NuGet Package Manager

  4. Click on I Accept in the License Acceptance window:

    Using the NuGet Package Manager

  5. Once you click on I Accept , it will install the Entity Framework with all its dependencies. In the Output window, you will get the Finished message once the installation is complete:

    Using the NuGet Package Manager

使用包管理控制台

要使用包管理器控制台安装NuGet包,请遵循以下步骤:

  1. Open the Package Manager Console window by selecting the menu option View | Other Windows | Package Manager Console .

    Using the Package Manager Console

  2. Type Install-Package EntityFramework.MicrosoftSqlServer - Pre in the Package Manager Console window as shown in the following screenshot:

    Using the Package Manager Console

  3. Once the installation is complete, a message, Successfully installed 'EntityFramework.MicrosoftSqlServer 7.0.0-rc1-final' , will be shown:

    Using the Package Manager Console

安装实体框架命令

为了执行迁移活动,我们需要安装实体框架命令包。 迁移包括数据库及其相关表的创建。 模式中的任何变化也将通过迁移来处理:

Installing Entity Framework commands

正如前面所讨论的,当我们使用实体框架时,我们需要遵循三个步骤来与数据库交互:

  1. 创建Model类。
  2. 为您的业务域对象创建DbContext类。 类的实例表示与数据库的会话。
  3. 构造业务领域对象并使用DBContext类的实例将其保存到数据库中。

让我们详细讨论前面的每个步骤,并尝试将对象保存到数据库中。

创建模型类

Model类是简单的 POCO 对象,可以与实体框架一起使用。

让我们为我们的业务领域对象创建一个 POCO 类,即本例中的Employee类。 我在控制台应用中创建了一个名为Employee.cs的新文件,其中包含以下内容。 这个Employee类包含雇员的一些属性,并且没有特殊的属性或字段来与实体框架一起工作。

让我们看看下面的代码片段:

public class Employee { 
  public int EmployeeId { get; set; } 
  public string Name { get; set; } 
  public decimal Salary { get; set; } 
  public string Designation { get; set; } 
} 

按照惯例,如果属性名是IdClassName+Id,实体框架在创建数据库表时将其视为主键。

具有字符串数据类型的属性将被创建为类型为nvarchar(max)的字段。 但是,我们可以通过使用注释来覆盖这种行为,我们将在后面讨论。

创建 DbContext 类

DbContext类的实例表示到数据库的会话,而DbContext类为应用完成大部分繁重的数据访问。

通过命名的EmployeeDbContext创建一个新类,内容如下:

using Microsoft.Data.Entity; 
using System.Configuration; 

namespace ConsoleEF7 { 
  public class EmployeeDbContext : DbContext{ 
    public DbSet<Employee> Employees {get; set;} 

    protected override void OnConfiguring(DbContextOptionsBuilder      optionsBuilder) {string connectionString =        ConfigurationManager.ConnectionStrings       ["SqlServerExpress"].ConnectionString; 
      optionsBuilder.UseSqlServer(connectionString); 
      base.OnConfiguring(optionsBuilder); 
    } 
  } 
} 

使用App.Config配置它:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
  <startup> 
    <supportedRuntime version="v4.0"  
    sku=".NETFramework,Version=v4.6.1" /> 
  </startup> 
  <connectionStrings> 
    <add name="SqlServerExpress" connectionString="Data Source=     MUGIL-PC\SQLEXPRESS;Initial Catalog=EF7Console;Integrated      Security=True"/> 
  </connectionStrings> 
</configuration> 

在前面的代码片段中,有一些事情需要注意:

  • Microsoft.Data.Entity命名空间作为这个命名空间中可用的DbContext类。 我们的连接字符串可以在App.Config文件中找到。 为了阅读App.Config文件的内容,我们将ConfigurationManager类包含在System.Configuration中。
  • 为了使用DbContextAPI,必须创建一个继承自DbContext类的类,这样我们才能访问DbContextAPI 的方法。 我们创建了从DbContext类继承而来的EmployeeDbContext类。
  • DbSet是一个类,它允许对给定的实体类型执行实体框架操作。 我们需要为应用中使用的每个 Entity 类型创建DbSet对象。 在本例中,我们只使用了一个DbSet对象,因为我们正在处理Employee类。

创建迁移

迁移是记录数据库所有变更的过程。 Add-Migration是用于添加迁移的实体框架命令:

Create a migration

  1. Once you add the migration, you can revoke the changes by executing the  Remove-Migration Entity Framework command.

    Create a migration

    • This is what the migrations directory looks like:

      Create a migration

  2. Update the database by issuing the Entity Framework command Update-Database  , which updates the database tables as per the information available in the migration. As we have installed the EntityFramework.Commands package earlier, these commands will be available for the application:

    Create a migration

  3. Once you update the database, you can see the changes in the database by connecting to SQL Server Management Studio:

    Create a migration

  4. 执行数据库操作,将业务域对象保存在数据库中。 您可以手动创建数据库,或者,如果数据库不可用,它将为您创建一个。

方法更新为以下代码:

class Program { 
  static void Main(string[] args) { 
    AddEmployee(); 
  } 

  static void AddEmployee() { 
    using (var db = new EmployeeDbContext()) { 
      Employee employee= new Employee { 
        Designation = "Software Engineer", 
        Name = "Scott", 
        Salary = 5600 
      }; 

      db.Employees.Add(employee); 
      int recordsInserted = db.SaveChanges(); 
      Console.WriteLine("Number of records inserted:" +        recordsInserted); 
      Console.ReadLine();
    } 
  } 
} 

首先,我们构造业务领域对象。 然后,我们将构造的Employee对象添加到DbContext类的员工的DbSet。 最后,我们调用SaveChanges方法DbContextAPI,它将把所有挂起的更改保存到数据库中。

您可能想知道,当我们甚至没有给出连接字符串时,它如何将其保存到数据库。

让我们来讨论一下当我们运行程序时,在幕后发生了什么:

  • 当您更改任何DbSet集合时,实体框架将检查数据库是否存在。 如果不存在,则使用模式<Namespace of DbContextName>创建一个新的。 在本例中,将创建一个由EF6.EmployeeDbContext调用的数据库。
  • 然后,它为DbSet中声明的实体创建数据库表。 根据约定,实体框架使用 Entity 的复数形式作为表名。 由于我们为Employee实体声明了DbSet,实体框架创建了Employee的复数形式,并创建了名为Employees的表。

数据库和表的创建发生在执行以下代码时:

db.Employees.Add(employee); 

当执行SaveChanges方法时,Employee对象中的数据将被保存到数据库中,并返回受影响的记录数量。 在前面的例子中,它返回1

当再次运行应用时,前面提到的前两个步骤将被跳过,因为已经创建了数据库和表。

查询数据库时,可以看到新插入的记录:

Create a migration

savchanges 方法的工作原理

当我们进行更改时,实体框架跟踪每个对象的状态,并在调用SaveChanges方法时执行适当的查询。

例如,当我们向雇员集合(DbSet)添加一个Employee对象时,该对象将被跟踪为处于Added状态的Entity。 当调用SaveChanges时,实体框架为其创建一个insert查询并执行该查询。 更新和删除对象的情况也是如此。 实体框架将各自对象的Entity状态设置为ModifiedDeleted。 当调用SaveChanges时,它创建并执行UpdateDelete查询。

How the SaveChanges method works

上图说明了SaveChanges方法在不同类型的变更的高层中是如何工作的。 我们有两个 POCO 对象(对象 1对象 2),它们已经被添加到员工的DbSet对象中。 让我们假设对象 3对象 4已经被修改,而对象对象 5对象 6处于Deleted状态。 当调用SaveChanges方法时,它将创建三组查询。 第一组查询用于添加对象,结果是对数据库执行insert查询。 在第二组查询中,将为其状态被修改的对象创建并执行Update查询。 最后,对所有Deleted状态对象的对象执行Delete查询。

更新记录

让我们尝试使用实体框架更新插入的员工记录的工资:

static void UpdateSalary() { 
  using (var db = new EmployeeDbContext()){ 
    Employee employee = db.Employees.Where(emp => emp.EmployeeId      == 1).FirstOrDefault(); 
    if(employee!=null){
      employee.Salary = 6500; 
      int recordsUpdated = db.SaveChanges(); 
      Console.WriteLine("Records updated:" + recordsUpdated); 
      Console.ReadLine(); 
    }
  } 
} 

在前面的方法中,我们找到了具有EmployeeId = 1的员工。 然后,我们将员工的工资更新为6500,并将employee对象保存到数据库中。 请注意,在前面的方法中,我们与数据库进行了多次交互——一次是查找正确的员工记录(read操作),另一次是更新记录(update操作)。

static void Main(string[] args){
  UpdateSalary(); 
} 

更新Main方法以调用UpdateSalary方法。 当你查询数据库时,你应该看到有更新信息的记录:

Updating the record

删除记录

删除记录有点棘手,因为它涉及直接设置状态。 在下面的方法中,首先我们获取对象,并将对象的状态设置为Deleted。 然后调用SaveChanges方法生成对象的delete查询,并执行该查询,从而最终删除数据库中的记录:

static void DeleteEmployee() { 
  using (var db = new EmployeeDbContext()) { 
    Employee employeeToBeDeleted = db.Employees.Where(emp =>      emp.EmployeeId == 1).FirstOrDefault(); 
    if (employeeToBeDeleted != null) { 
      db.Entry(employeeToBeDeleted).State =        Microsoft.Data.Entity.EntityState.Deleted; 
      int recordsDeleted = db.SaveChanges(); 
      Console.WriteLine("Number of records deleted:" +        recordsDeleted); 
      Console.ReadLine(); 
    } 
  } 
} 

static void Main(string[] args) { 
  DeleteEmployee(); 
} 

在 ASP 中使用实体框架。 净 MVC 应用

在控制台应用中使用实体框架和在 asp.net 中使用实体框架之间没有太大的区别。 净 MVC 应用。 现在,我们将构建一个简单的应用,它只有一个屏幕,如下图所示。 在这个屏幕中,我们将有一个表单,用户将在其中输入关于员工的信息; 一旦用户提交表单,信息将被保存到数据库中,并反映在以下截图中:

Using the Entity Framework in ASP.NET MVC applications

我们可以为员工创建一个简单的 Model。 我们需要为这个视图构建一个 ViewModel,因为我们需要从用户那里获得员工信息,我们还需要在同一个屏幕上显示员工列表。

让我们创建一个 ASP.NET Core 应用,添加员工并显示员工列表。 以下是为上述目标创建应用的逐步说明:

  1. 创建一个 ASP。 在 Visual Studio 中选择一个空的 asp.NET Core 项目。 净 5 应用。
  2. 安装 ASP.NET CoreNuGet包。
  3. 安装实体框架 7NuGet包和 **ef** EntityFramework 命令(用于数据库迁移),如本章前面所述。
  4. 添加config.json来声明数据库的连接字符串:

    ``` { "Data": { "DefaultConnection": { "ConnectionString": "Data Source=MUGIL-PC\SQLEXPRESS;Initial Catalog=Validation;Integrated Security=True" } } }

    ```

  5. 更新project.json以包含 EntityFramework 7 和 EntityFramework 命令。 更改以粗体显示:

    ``` { "version": "1.0.0-*", "compilationOptions":{ "emitEntryPoint": true },

    "dependencies": { "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final", "Microsoft.AspNet.Mvc": "6.0.0-rc1-final", "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",

    "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final", "EntityFramework.Commands": "7.0.0-rc1-final"

    },

    "commands": { "web": "Microsoft.AspNet.Server.Kestrel",

    "ef": "EntityFramework.Commands"

    },

    "frameworks": { "dnx451": { }, "dnxcore50": { } },

    "exclude": [ "wwwroot", "node_modules" ], "publishExclude": [ ".user", ".vspscc" ] }

    ```

  6. Startup类(Startup.cs)中配置 MVC:

    • 在构造函数中,我们通过读取config.json文件来构建配置
    • 将 MVC 服务和实体框架服务添加到ConfigureServices方法中的服务中
    • Configure方式配置 MVC 路由:

      ``` using Microsoft.AspNet.Builder; using Microsoft.AspNet.Hosting; using Microsoft.AspNet.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Configuration; using Validation.Models; using Microsoft.Data.Entity; using Microsoft.Extensions.PlatformAbstractions;

      namespace Validation { public class Startup { public IConfigurationRoot Configuration { get; set; }

      public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv) { var builder = new ConfigurationBuilder() .AddJsonFile("config.json") .AddEnvironmentVariables(); Configuration = builder.Build(); }

      // This method gets called by the runtime. Use this method to add services to the container. // For more information on how to configure your application, visit http ://go.microsoft.com/fwlink/?LinkID=398940

      public void ConfigureServices(IServiceCollection services) { services.AddEntityFramework() .AddSqlServer() .AddDbContext(options => { options.UseSqlServer(Configuration.Get ("Data:DefaultConnection:ConnectionString")); }); services.AddMvc(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

      public void Configure(IApplicationBuilder app) { app.UseIISPlatformHandler(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Employee}/ {action=Index}/{id?}"); }); } // Entry point for the application. public static void Main(string[] args) => WebApplication.Run(args); } } ```

  7. 创建ModelsDbContext类。

  8. 创建Models文件夹,并添加Employee模型类和EmployeeDbContext类。
  9. 创建Employee模型类(Employee.csModels文件夹中):

    ``` public class Employee { public int EmployeeId { get; set; } public string Name { get; set; } public string Designation { get; set; } public decimal Salary { get; set; } }

    ```

  10. 创建EmployeeDbContext(EmployeeDbContext.csModels文件夹中):

    ``` using Microsoft.Data.Entity; using Microsoft.Extensions.Configuration;

    namespace Validation.Models { public class EmployeeDbContext : DbContext {

    public IConfigurationRoot Configuration { get; set; }
    
    public DbSet<Employee> Employees { get; set; }
    
    public EmployeeDbContext() { 
      var builder = new ConfigurationBuilder() 
      .AddJsonFile("config.json") 
      .AddEnvironmentVariables(); 
      Configuration = builder.Build(); 
    }
    
    protected override void OnConfiguring     (DbContextOptionsBuilder optionsBuilder) {      optionsBuilder.UseSqlServer       (Configuration.Get<string>       ("Data:DefaultConnection:ConnectionString")); 
      base.OnConfiguring(optionsBuilder); 
    }
    

    } }

    ```

  11. 创建 T0:

    • 由于我们将显示员工列表和在同一个屏幕中添加员工的表单,所以我们将构建一个特定于此视图的模型。 该模型将包含关于雇员列表和要添加的雇员的信息。
  12. 创建ViewModels文件夹并添加EmployeeAddViewModel:

    ``` using MVCEF7.Models;

    namespace MVCEF7.ViewModels { public class EmployeeAddViewModel { public List EmployeesList { get; set; } public Employee NewEmployee { get; set; } } }

    ```

    • 这个ViewModel有几个属性。 EmployeesListNewEmployeeEmployeesList将包含员工列表。 这个列表将从数据库中获取。 NewEmployee将保存用户输入的员工信息。
    • 创建Controllers来处理传入的请求:
    • 创建一个Controllers文件夹,并添加EmployeeController类和两个操作方法——一个用于GET,另一个用于POST。 当您访问 URL(http://localhost/Employee/Index)或运行应用时,将调用与GET操作方法对应的Index操作方法。 当您按以下方式提交表单时,将调用POST Index动作方法:
    • 在前面的GET Index操作方法中,我们创建了ViewModel对象并将其传递给 View。
    • 下面的代码使用了POST Index动作方法:

      ``` [HttpPost] public IActionResult Index(EmployeeAddViewModel employeeAddViewModel) {

      using (var db = new EmployeeDbContext()) { db.Employees.Add(employeeAddViewModel.NewEmployee); db.SaveChanges(); //Redirect to get Index GET method return RedirectToAction("Index"); }

      }

      ```

    • 我们在 ViewModel 中获得了NewEmployee属性,它包含关于用户的信息。 保存到数据库中。 一旦我们将员工信息保存到数据库,并将控件重定向到GET Index操作方法,GET Index操作方法将再次显示表单,以表格格式输入员工信息和员工列表。

    • 添加Views文件夹:
    • 创建包含以下内容的Views\_ViewStart.cshtml
    • 创建包含以下内容的Views\Shared\_Layout.cshtml
    • 创建包含以下内容的Views\Employee\Index.cshtml

在前面的Index视图中,我们创建了一个表单,从最上面的div中获取用户的员工信息。 在下一个div中,我们以表格格式显示员工列表。

一旦我们创建了所有的文件夹和文件,项目结构应该如下所示:

Using the Entity Framework in ASP.NET MVC applications

数据库迁移

我们已经创建了业务实体——Employee类。 现在,我们可以继续迁移。 迁移过程分为两步:在第一步中,我们创建迁移文件。 这可以通过从项目上下文的命令提示符中执行以下命令来实现:

dnx ef migrations add InitialMigration

Database migration

这个命令将在你的项目中创建迁移文件,如下图所示:

Database migration

然后执行如下命令创建数据库:

Database migration

这个命令将读取在上一步中创建的迁移文件,并创建数据库和相关的表:

Database migration

运行应用。 您将看到以下屏幕,其中用户可以在表单中输入员工信息。 因为我们在视图中使用强类型模型,所以所有属性都采用默认值。 NameDesignation``string类型的属性,这些字段的默认值是空字符串,Salary``decimal类型,默认值为decimal0因此0所示的形式加载时【显示】字段。

由于没有记录,我们在List of employees表中显示0记录:

Database migration

当您在表单中输入信息并提交时,将信息保存到数据库中,Employees表中的所有数据库记录将显示如下:

Database migration

总结

在本章中,我们学习了什么是模型,以及它如何适应 ASP。 净 MVC 应用。 然后,我们创建一个简单的模型,在控制器中构建模型数据,将模型传递给视图,并使用视图显示数据。 我们已经了解了特定于视图的模型,并讨论了与模型相关的数据流。 我们学习了实体框架,这是微软的一个 ORM 框架,以及它如何简化。net 应用的数据库访问。 我们创建了简单的控制台应用,在其中插入、更新和删除了记录。 最后,我们建立了一个 ASP.NET Core 应用,使用模型、ViewModel 和实体框架。