ASP.NET MVC3教程
ASP.NET MVC3 电影示例系列:共九篇 [文章列表]
这里的文章是ASP.NET官网的教程,这里做翻译而已,才疏学浅,翻译错误的地方,请指正,原文地址:Adding a New Field to the Movie Model and Table(C#)
在本节中你将会对模型类做一些修改,并且你将学习如何更新数据库结构来匹配模型的修改。
为Movie模型添加一个评级(Rating)属性
从为现存的Movie类田间一个新的评级属性作为开始。打开Movie.cs文件,想下面这样添加评级属性:
public string Rating { get; set; }
完成的Movie类现在看起来如下:
public class Movie
{
public int ID { get; set; }
public string Title { get; set; }
public DateTime ReleaseDate { get; set; }
public string Genre { get; set; }
public decimal Price { get; set; }
public string Rating { get; set; }
}
通过调试(Debug)> 生成Movie(Build Movie)菜单命令重新编译应用程序。
现在你已经更新完了模型类,为了支持新的评级属性,你同样需要更新\Views\Movies\Index.cshtml 和 \Views\Movies\Create.Cshtml 视图模板。
打开\Views\Movies\Index.cshtml文件,并在紧接Price列后面添加<th>Rating</th>列头。之后在模板的末尾附近添加<td>列来生成@item.Rating值。更新后的Index.cshtml视图模板看起来像下面这样:
<table>
<tr>
<th></th>
<th>Title</th>
<th>Release Date</th>
<th>Genre</th>
<th>Price</th>
<th>Rating</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.ReleaseDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Genre)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Rating )
</td>
<td>
@Html.ActionLink("Edit Me", "Edit", new { id=item.ID }) |
@Html.ActionLink("Details", "Details", new { id=item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.ID })
</td>
</tr>
}
</table>
而后,打开\Views\Movies\Create.cshtml文件,并且在靠近form的末尾处添加下面的标记。这将生成一个文本框,当新添新电影是你可以指定一个评级。
<div class="editor-label">
@Html.LabelFor(model => model.Rating)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Rating)
@Html.ValidationMessageFor(model => model.Rating)
</div>
处理模型和数据库结构之间的差异
现在你已经更新了应用程序的代码来支持新的评级属性。
现在运行应用程序并将URL导航到/Movies。然而,当你这么操作的时候,你将会看到如下的错误:
你看到的这个错误是因为应用程序中更新后的Movie模型现在和当下数据库中的Moive表结构不一致。(在数据库表中没有Rating列。)
默认情况下,当你使用Entity Framework Code First来自动创建数据库,就像你在本教程之前做的那样,Code First 会添加一个表到数据库中,用来帮助跟踪数据库框架和生成它的原始模型类是否同步。如果他们不同步,Entity Framework将抛出一个错误。这使得那些你原来可能仅能在运行时发现的错误(模糊的错误)变得更容易在开发时就能被追踪到。你刚刚看到的错误信息就是同步检测特性引发的。
这里有两个方法来解决这个错误:
1. 让Entity Framework自动Drop并基于新的模型类结构重建数据库。这个方法在测试数据库上执行快速开发的时候非常方便1,因为它允许你快速的使模型和数据库结构同步变化。然而,负面影响是你会丢失数据库现有的数据 —— 因此,你不会想在产品环境的数据库上使用这个方法。
2. 明确的修改现存数据库中的结构,以便能够匹配上模型类。这个方法的优势是你能够保存你的数据。你可以通过手动或者创建数据库修改脚本来执行修改。
在本教程中,我们使用第一种方法 —— 你将使用Entity Framework Code First在模型改变的任何时候自动重建数据库。
在模型更改时自动重建数据库
让我们更新下应用程序,以便Code First能在任何你修改此应用程序的模式时自动删除并重建数据库。
警告(Warning):你应该仅在你使用开发用或测试数据库的时候启用这个方法来自动删除和重建数据库,永远不要在包含真实数据的生产数据库中使用。在生产服务器上会导致数据的丢失。
在解决方案资源管理器中,右键点击Models文件夹,选择添加,而后选择类。
将类命名为"MovieInitializer".更改MovieInitializer类包含下面代码:
using System;
using System.Collections.Generic;
using System.Data.Entity;
namespace MvcMovie.Models {
public class MovieInitializer : DropCreateDatabaseIfModelChanges<MovieDBContext> {
protected override void Seed(MovieDBContext context) {
var movies = new List<Movie> {
new Movie { Title = "When Harry Met Sally",
ReleaseDate=DateTime.Parse("1989-1-11"),
Genre="Romantic Comedy",
Rating="R",
Price=7.99M},
new Movie { Title = "Ghostbusters ",
ReleaseDate=DateTime.Parse("1984-3-13"),
Genre="Comedy",
Rating="R",
Price=8.99M},
new Movie { Title = "Ghostbusters 2",
ReleaseDate=DateTime.Parse("1986-2-23"),
Genre="Comedy",
Rating="R",
Price=9.99M},
new Movie { Title = "Rio Bravo",
ReleaseDate=DateTime.Parse("1959-4-15"),
Genre="Western",
Rating="R",
Price=3.99M},
};
movies.ForEach(d => context.Movies.Add(d));
}
}
}
MovieInitializer类指明模型使用的数据库在模型类发生改变之后需要删除并且自动重建。代码中包含Seed方法用来指定一些默认的数据,在任何时候数据库创建(或重建)时自动添加到数据库中。这提供了一个非常有用的方法来为数据库填充一些示例数据,而不用每次在你修改模型之后手动填充。
既然你已经定义了一个MovieInitializer类,你也许想连接起来一边每次程序运行的时候2,它都会检查模型类是否和数据库中的结构不同。如果不同,你可以运行initializer重建数据库来匹配模型,而后用示例数据填充数据库。
打开在MvcMovies项目根下的Global.asax文件:
Global.asax文件包含定义项目的全局应用的类3,它包含了一个在应用程序第一次开始运行的事件句柄Application_Start。
让 我们在文件的顶部加上两个using语句。第一个应用Entity Framework的命名空间,第二个我们引用我们MovieInitializer类所在的命名空间:
using System.Data.Entity; // Database.SetInitialize
using MvcMovie.Models; // MovieInitializer
之后找到Application_Start方法,在方法的起始位置添加对Database.SetInitializer的调用,如下所示:
protected void Application_Start()
{
Database.SetInitializer<MovieDBContext>(new MovieInitializer());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
你刚刚添加的Database.SetInitializer语句指明:MovieDBContext使用的数据库实例在和数据库结构不匹配的时候,自动删除并重建数据库。正如你所看到的那样,它还会根据MoviInitializer类中指定的示例数据填充新数据库。
关闭Global.asax文件。
重新运行应用程序并将URL导航到/Movies。它察觉模型结构不再和数据库结构匹配。它将自动重建与新模型结构匹配的数据库并用示例电影数据填充数据库:
点击新建(Create New)链接来添加一部新电影。现在你会看到你可以添加评级了。
点击创建(Create)。包含评级的新电影,现在就出现在电影列表里面了:
在本节里,你看到了应该如何修改模型对象并且让数据库保持与之同步修改。你也学到了为一个新创建的数据库填充示例数据的方法,你可以在各种方案中尝试4。下一步,让我们着手于如何为模型类添加更丰富的校验逻辑并启用一些业务规则5。
MitchellChu翻译中未决参考:
1. active development:不知道怎么解释,这里作为"开发"翻译。
2. wire it up: 这个意思翻译不准确,谁知道请指点,这里译作了“连接起来"。
3. the entire application for the project:这里entire application指的是MVCApplication,这里翻译成"全局应用"。
4. ... so you can try out scenarios:这个翻译似乎不太准确。
5. ... enable some business rules to be enforced.:翻译成:启用一些业务规则。