将新字段添加到 ASP.NET Core MVC 应用
在此部分中,Entity Framework Code First 迁移用于:
- 将新字段添加到模型。
- 将新字段迁移到数据库。
使用 EF Code First 自动创建数据库时,Code First 将:
- 将表添加到数据库,以跟踪数据库的架构。
- 验证数据库与生成它的模型类是否同步。 如果它们不同步,EF 则会引发异常。 这使查找不一致的数据库/代码问题变得更加轻松。
向电影模型添加分级属性
将 Rating
属性添加到 Models/Movie.cs :
public class Movie { public int Id { get; set; } public string Title { get; set; } [Display(Name = "Release Date")] [DataType(DataType.Date)] public DateTime ReleaseDate { get; set; } public string Genre { get; set; } [Column(TypeName = "decimal(18, 2)")] public decimal Price { get; set; } public string Rating { get; set; } }
生成应用
-
Visual Studio
Ctrl+Shift+B
-
Visual Studio Code
dotnet build
-
Visual Studio for Mac
命令 ⌘ + B
因为已经添加新字段到 Movie
类,所以需要更新绑定允许名单,将此新属性纳入其中。 在 MoviesController.cs 中,更新 Create
和 Edit
操作方法的 [Bind]
属性,以包括 Rating
属性:
[Bind("Id,Title,ReleaseDate,Genre,Price,Rating")]
更新视图模板以在浏览器视图中显示、创建和编辑新的 Rating
属性。
编辑 /Views/Movies/Index.cshtml 文件并添加 Rating
字段 :
<thead> <tr> <th> @Html.DisplayNameFor(model => model.Movies[0].Title) </th> <th> @Html.DisplayNameFor(model => model.Movies[0].ReleaseDate) </th> <th> @Html.DisplayNameFor(model => model.Movies[0].Genre) </th> <th> @Html.DisplayNameFor(model => model.Movies[0].Price) </th> <th> @Html.DisplayNameFor(model => model.Movies[0].Rating) </th> <th></th> </tr> </thead> <tbody> @foreach (var item in Model.Movies) { <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> <a asp-action="Edit" asp-route-id="@item.Id">Edit</a> |
使用 Rating
字段更新 /Views/Movies/Create.cshtml 。
-
Visual Studio / Visual Studio for Mac
可以复制/粘贴之前的“窗体组”,并让 intelliSense 帮助更新字段。 IntelliSense 适用于标记帮助程序。
-
Visual Studio Code
更新剩余模板。
更新 SeedData
类,使它提供新列的值。 示例更改如下所示,但可能需要对每个 new Movie
做出此更改。
new Movie { Title = "When Harry Met Sally", ReleaseDate = DateTime.Parse("1989-1-11"), Genre = "Romantic Comedy", Rating = "R", Price = 7.99M },
在 DB 更新为包括新字段之前,应用将不会正常工作。 如果它现在运行,将引发以下 SqlException
:
SqlException: Invalid column name 'Rating'.
发生此错误是因为更新的 Movie 模型类与现有数据库的 Movie 表架构不同。 (数据库表中没有 Rating
列。)
可通过几种方法解决此错误:
让 Entity Framework 自动丢弃,并基于新的模型类架构重新创建数据库。 在测试数据库上进行开发时,此方法在开发周期早期很方便;通过它可以一起快速改进模型和数据库架构。 但其缺点是会丢失数据库中的现有数据 - 因此请勿对生产数据库使用此方法! 使用初始值设定项,以使用测试数据自动设定数据库种子,这通常是开发应用程序的有效方式。 对于早期开发和使用 SQLite 的情况,这是一个不错的方法。
对现有数据库架构进行显式修改,使它与模型类相匹配。 此方法的优点是可以保留数据。 可以手动或通过创建数据库更改脚本进行此更改。
使用 Code First 迁移更新数据库架构。
对于本教程,请使用 Code First 迁移。
-
Visual Studio
从“工具”菜单中,选择“NuGet 包管理器”>“包管理器控制台”。
在 PMC 中,输入以下命令:
Add-Migration Rating Update-Database
Add-Migration
命令会通知迁移框架使用当前Movie
DB 架构检查当前Movie
模型,并创建必要的代码,将 DB 迁移到新模型。名称“Rating”是任意的,用于对迁移文件进行命名。 为迁移文件使用有意义的名称是有帮助的。
如果删除 DB 中的所有记录,初始化方法会设定 DB 种子,并将包括
Rating
字段。 -
Visual Studio Code / Visual Studio for Mac
备注
在本教程中,使用 Entity Framework Core 迁移功能(若可行) 。 迁移会更新数据库架构,使其与数据模型中的更改相匹配。 但是,迁移仅能执行 EF Core 提供程序所支持的更改类型,且 SQLite 提供程序的功能将受限。 例如,支持添加列,但不支持删除或更改列。 如果已创建迁移以删除或更改列,则
ef migrations add
命令将成功,但ef database update
命令会失败。 由于上述限制,本教程不对 SQLite 架构更改使用迁移。 转而在架构更改时,放弃并重新创建数据库。要绕开 SQLite 限制,可手动写入迁移代码,在表内容更改时重新生成表。 表重新生成涉及:
- 创建新表。
- 将旧表中的数据复制到新表中。
- 放弃旧表。
- 为新表重命名。
有关更多信息,请参见以下资源:
删除数据库并通过迁移重新创建数据库。 若要删除该数据库,请删除数据库文件 (MvcMovie.db) 。 然后运行
ef database update
命令:dotnet ef database update
运行应用,并验证是否可以创建/编辑/显示具有 Rating
字段的电影。 应向 Edit
、Details
和 Delete
视图模板添加 Rating
字段。