Nguon: Microsoft Learn · .NET 8.0

Phần 8: Thêm trường mới vào ứng dụng ASP.NET Core MVC

Nguồn: Part 8, add a new field to an ASP.NET Core MVC app

Trong phần này, Entity Framework Core migrations (công cụ di chuyển) được sử dụng để:

Khi EF Code First (EF theo hướng Code trước) được sử dụng để tự động tạo cơ sở dữ liệu, Code First:

Thêm thuộc tính Rating vào Movie Model

Thêm thuộc tính Rating vào Models/Movie.cs:

csharp
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MvcMovie.Models;

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; }
}

Build (xây dựng) ứng dụng:

Visual Studio: Nhấn Ctrl+Shift+B

Visual Studio Code: Từ menu View, chọn Terminal và nhập lệnh:

dotnetcli
dotnet build

Vì bạn đã thêm một trường mới vào class Movie, bạn cần cập nhật danh sách binding thuộc tính để thuộc tính mới này sẽ được bao gồm. Trong MoviesController.cs, cập nhật thuộc tính [Bind] cho cả hai action method CreateEdit để bao gồm thuộc tính Rating:

csharp
[Bind("Id,Title,ReleaseDate,Genre,Price,Rating")]

Cập nhật các view template (mẫu hiển thị) để hiển thị, tạo và chỉnh sửa thuộc tính Rating mới trong browser view.

Chỉnh sửa file /Views/Movies/Index.cshtml và thêm một trường Rating:

cshtml
<table class="table">
    <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> |
                    <a asp-action="Details" asp-route-id="@item.Id">Details</a> |
                    <a asp-action="Delete" asp-route-id="@item.Id">Delete</a>
                </td>
            </tr>
        }
    </tbody>
</table>

Cập nhật /Views/Movies/Create.cshtml với một trường Rating. Bạn có thể copy/paste "form group" trước đó và để IntelliSense giúp bạn cập nhật các trường. IntelliSense hoạt động với Tag Helpers (trình trợ giúp thẻ).

Thêm thuộc tính Rating vào các template còn lại (Create.cshtml, Delete.cshtml, Details.cshtml, và Edit.cshtml).

Cập nhật class SeedData để cung cấp giá trị cho cột mới. Một thay đổi mẫu được hiển thị trong đoạn code sau, nhưng bạn sẽ muốn thực hiện thay đổi này cho mỗi new Movie.

csharp
new Movie
{
    Title = "When Harry Met Sally",
    ReleaseDate = DateTime.Parse("1989-1-11"),
    Genre = "Romantic Comedy",
    Rating = "R",
    Price = 7.99M
},

Ứng dụng sẽ không hoạt động cho đến khi DB (cơ sở dữ liệu) được cập nhật để bao gồm trường mới. Nếu chạy ngay bây giờ, SqlException sau sẽ được ném ra:

SqlException: Invalid column name 'Rating'.

Lỗi này xảy ra vì class Movie model được cập nhật khác với schema của bảng Movie trong cơ sở dữ liệu hiện có. (Không có cột Rating trong bảng cơ sở dữ liệu.)

Có một số cách tiếp cận để giải quyết lỗi:

  1. Để Entity Framework tự động drop (xóa) và tạo lại cơ sở dữ liệu dựa trên schema của model class mới. Cách tiếp cận này rất thuận tiện trong giai đoạn đầu của chu kỳ phát triển khi bạn đang phát triển tích cực trên cơ sở dữ liệu kiểm tra; nó cho phép bạn nhanh chóng phát triển model và schema cơ sở dữ liệu cùng nhau. Nhược điểm là bạn mất dữ liệu hiện có trong cơ sở dữ liệu — vì vậy bạn không muốn sử dụng cách tiếp cận này trên cơ sở dữ liệu sản xuất!
  2. Chỉnh sửa schema của cơ sở dữ liệu hiện có một cách rõ ràng để khớp với các model class. Ưu điểm của cách tiếp cận này là bạn giữ lại dữ liệu của mình.
  3. Sử dụng Code First Migrations để cập nhật schema cơ sở dữ liệu.

Trong hướng dẫn này, Code First Migrations được sử dụng.

Visual Studio

Từ menu Tools, chọn NuGet Package Manager > Package Manager Console.

Trong Package Manager Console (PMC), nhập các lệnh sau:

powershell
Add-Migration Rating
Update-Database

Lệnh Add-Migration yêu cầu migration framework (khung di chuyển) kiểm tra model Movie hiện tại với schema DB Movie hiện tại và tạo code cần thiết để di chuyển DB sang model mới.

Tên "Rating" là tùy ý và được sử dụng để đặt tên cho file migration. Nên sử dụng tên có ý nghĩa cho file migration.

Nếu tất cả các bản ghi trong DB bị xóa, method khởi tạo sẽ seed (gieo dữ liệu) DB và bao gồm trường Rating.

Visual Studio Code

Đối với hướng dẫn này, bạn sử dụng tính năng Entity Framework Core migrations nơi có thể. Migrations cập nhật schema cơ sở dữ liệu để khớp với các thay đổi trong data model. Tuy nhiên, migrations chỉ có thể thực hiện những loại thay đổi mà EF Core provider hỗ trợ, và các khả năng của SQLite provider bị hạn chế. Ví dụ, thêm một cột được hỗ trợ, nhưng xóa hoặc thay đổi một cột thì không. Vì những hạn chế này, hướng dẫn này không sử dụng migrations cho các thay đổi schema SQLite. Thay vào đó, khi schema thay đổi, bạn drop và tạo lại cơ sở dữ liệu.

Xóa thư mục Migrations và file cơ sở dữ liệu, sau đó chạy các lệnh .NET CLI sau:

dotnetcli
dotnet ef migrations add InitialCreate
dotnetcli
dotnet ef database update

Chạy ứng dụng và xác minh bạn có thể tạo, chỉnh sửa và hiển thị phim với trường Rating.