向电影模型和数据库表添加新字段 (VB)

作者: 里克·安德森

本教程将介绍如何使用 Microsoft Visual Web Developer 2010 Express Service Pack 1 生成 ASP.NET MVC Web 应用程序的基本知识,这是 visual Studio 的免费 Microsoft版本。 在开始之前,请确保已安装下面列出的先决条件。 可以通过单击以下链接来安装所有这些组件: Web 平台安装程序。 或者,可使用以下链接单独安装各个必备软件:

如果使用 Visual Studio 2010 而不是 Visual Web Developer 2010,请单击以下链接安装必备组件: Visual Studio 2010 先决条件

本主题随附了具有 VB.NET 源代码的 Visual Web 开发人员项目。 下载 VB.NET 版本。 如果需要 C#,请切换到 本教程的 C# 版本

在本部分中,你将对模型类进行一些更改,并了解如何更新数据库架构以匹配模型更改。

向电影模型添加分级属性

首先向 Rating 现有 Movie 类添加新属性。 打开 Movie.cs 文件并添加 Rating 如下所示的属性:

Public Property Rating() As String

完整的 Movie 类现在类似于以下代码:

Public Class Movie
    Public Property ID() As Integer
    Public Property Title() As String
    Public Property ReleaseDate() As Date
    Public Property Genre() As String
    Public Property Price() As Decimal
    Public Property Rating() As String
End Class

使用“调试>生成电影”菜单命令重新编译应用程序。

更新类后Model,还需要更新 \Views\Movies\Index.vbhtml 和 \Views\Movies\Create.vbhtml 视图模板以支持新Rating属性。

打开\Views\Movies\Index.vbhtml 文件,并在 Price 列后面添加列<th>Rating</th>标题。 然后,在模板末尾附近添加一列 <td> 来呈现 @item.Rating 值。 下面是更新 的 Index.vbhtml 视图模板如下所示:

<table>
    <tr>
        <th>            Title        </th>
        <th>            ReleaseDate        </th>
        <th>            Genre        </th>
        <th>            Price        </th>
        <th>Rating</th>
        <th></th>
    </tr>

@For Each item In Model
    Dim currentItem = item
    @<tr>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Title)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.ReleaseDate)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Genre)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Price)
        </td>
         <td>
            @Html.DisplayFor(Function(modelItem) currentItem.Rating)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", New With {.id = currentItem.ID}) |
            @Html.ActionLink("Details", "Details", New With {.id = currentItem.ID}) |
            @Html.ActionLink("Delete", "Delete", New With {.id = currentItem.ID})
        </td>
    </tr>
Next

</table>

接下来,打开 \Views\Movies\Create.vbhtml 文件,并在窗体末尾附近添加以下标记。 这会呈现一个文本框,以便在创建新电影时指定分级。

<div class="editor-label">
     @Html.LabelFor(Function(model) model.Rating)
 </div>
 <div class="editor-field">
     @Html.EditorFor(Function(model) model.Rating)
     @Html.ValidationMessageFor(Function(model) model.Rating)
 </div>

管理模型和数据库架构差异

现已更新应用程序代码以支持新 Rating 属性。

现在运行应用程序并导航到 /Movies URL。 不过,执行此操作时,会看到以下错误:

显示浏览器窗口的屏幕截图,其中显示一个错误,指出应用程序中的服务器错误。

你会看到此错误,因为应用程序中更新 Movie 的模型类现在不同于现有数据库的表架构 Movie 。 (数据库表中没有 Rating 列。)

默认情况下,使用 Entity Framework Code First 自动创建数据库时,如本教程前面所述,Code First 向数据库添加一个表,以帮助跟踪数据库的架构是否与生成的模型类同步。 如果它们未同步,则 Entity Framework 将引发错误。 这样就可以更轻松地在开发时跟踪你可能只在运行时发现(通过模糊错误)的问题。 同步检查功能是导致你刚才看到的错误消息的原因。

可通过两种方法解决错误:

  1. 让 Entity Framework 自动丢弃,并基于新的模型类架构重新创建数据库。 在测试数据库上执行活动开发时,此方法非常方便,因为它允许你快速发展模型和数据库架构。 不过,缺点是,在数据库中丢失现有数据,因此 你不想 在生产数据库中使用此方法!
  2. 对现有数据库架构进行显式修改,使它与模型类相匹配。 此方法的优点是可以保留数据。 可以手动或通过创建数据库更改脚本进行此更改。

在本教程中,我们将使用第一种方法 — 只要模型发生更改,就会自动重新创建实体框架代码。

在模型更改时自动重新创建数据库

让我们更新应用程序,以便每当更改应用程序的模型时,Code First 会自动删除并重新创建数据库。

注意

警告 :仅当使用开发或测试数据库时,才应启用此方法来自动删除和重新创建数据库,而 不要 对包含实际数据的生产数据库启用此方法。 在生产服务器上使用它可能会导致数据丢失。

解决方案资源管理器中,右键单击“模型”文件夹,选择“添加,然后选择“”。

显示解决方案资源管理器窗口的屏幕截图。在“模型”右键单击菜单中选择了“添加”,并在子菜单中选择“类”。

将类命名为“MovieInitializer”。 更新 MovieInitializer 类以包含以下代码:

using System;
Imports System
Imports System.Collections.Generic
Imports System.Data.Entity

Namespace MvcMovie.Models
    Public Class MovieInitializer
        Inherits DropCreateDatabaseIfModelChanges(Of MovieDBContext)
        Protected Overrides Sub Seed(ByVal context As MovieDBContext)
            Dim movies = New List(Of Movie) From {
             New Movie With {.Title = "When Harry Met Sally", .ReleaseDate = Date.Parse("1989-1-11"), .Genre = "Romantic Comedy", .Rating = "R", .Price = 7.99D},
             New Movie With {.Title = "Ghostbusters ", .ReleaseDate = Date.Parse("1984-3-13"), .Genre = "Comedy", .Rating = "R", .Price = 8.99D},
             New Movie With {.Title = "Ghostbusters 2", .ReleaseDate = Date.Parse("1986-2-23"), .Genre = "Comedy", .Rating = "R", .Price = 9.99D},
             New Movie With {.Title = "Rio Bravo", .ReleaseDate = Date.Parse("1959-4-15"), .Genre = "Western", .Rating = "R", .Price = 3.99D}}

            movies.ForEach(Function(d) context.Movies.Add(d))
        End Sub
    End Class
End Namespace

MovieInitializer 类指定应删除模型使用的数据库,并在模型类发生更改时自动重新创建。 该代码包含一种方法 Seed ,用于指定一些默认数据,以在创建数据库时自动添加到数据库(或重新创建)。 这提供了一种有用的方法来使用一些示例数据填充数据库,而无需在每次更改模型时手动填充它。

定义类后 MovieInitializer ,需要连接该类,以便每次应用程序运行时,都会检查模型类是否与数据库中的架构不同。 如果是,可以运行初始值设定项以重新创建数据库以匹配模型,然后使用示例数据填充数据库。

打开位于项目根目录MvcMovies的 Global.asax 文件:

Global.asax 文件包含定义项目整个应用程序的类,并包含一个Application_Start在应用程序首次启动时运行的事件处理程序。

找到该方法 Application_Start 并在方法开头添加调用 Database.SetInitializer ,如下所示:

Sub Application_Start()
        System.Data.Entity.Database.SetInitializer(Of MovieDBContext)(New MvcMovie.Models.MovieInitializer())
       
        AreaRegistration.RegisterAllAreas()

        RegisterGlobalFilters(GlobalFilters.Filters)
        RegisterRoutes(RouteTable.Routes)
    End Sub

刚刚添加的 Database.SetInitializer 语句表示,如果架构和数据库不匹配,则实例使用 MovieDBContext 的数据库应自动删除并重新创建。 正如你所看到的,它还将使用类中指定的 MovieInitializer 示例数据填充数据库。

关闭 Global.asax 文件。

重新运行应用程序并导航到 /Movies URL。 应用程序启动时,它会检测到模型结构不再与数据库架构匹配。 它会自动重新创建数据库以匹配新的模型结构,并使用示例电影填充数据库:

7_MyMovieList_SM

单击“新建”链接添加新电影。 请注意,可以添加分级。

7_CreateRioII

单击 “创建” 。 新电影,包括评级,现在显示在电影列表:

7_ourNewMovie_SM

本部分介绍了如何修改模型对象,并使数据库与更改保持同步。 你还了解了使用示例数据填充新创建的数据库的方法,以便可以试用方案。 接下来,让我们看看如何向模型类添加更丰富的验证逻辑,以及如何强制实施一些业务规则。