Część 8 Dodaj nowe pole do aplikacji ASP.NET Core MVCPart 8, add a new field to an ASP.NET Core MVC app

Autor: Rick AndersonBy Rick Anderson

W tej sekcji Entity Framework migracje Code First służy do:In this section Entity Framework Code First Migrations is used to:

  • Dodaj nowe pole do modelu.Add a new field to the model.
  • Migruj nowe pole do bazy danych.Migrate the new field to the database.

Gdy Code First EF jest używany do automatycznego tworzenia bazy danych, Code First:When EF Code First is used to automatically create a database, Code First:

  • Dodaje tabelę do bazy danych w celu śledzenia schematu bazy danych.Adds a table to the database to track the schema of the database.
  • Weryfikuje, czy baza danych jest zsynchronizowana z klasami modelu, z których została wygenerowana.Verifies the database is in sync with the model classes it was generated from. Jeśli nie są zsynchronizowane, EF zgłasza wyjątek.If they aren't in sync, EF throws an exception. Ułatwia to znalezienie niespójnych problemów z bazą danych i kodem.This makes it easier to find inconsistent database/code issues.

Dodawanie właściwości oceny do modelu filmuAdd a Rating Property to the Movie Model

Dodaj Rating Właściwość do modeli/filmów. cs:Add a Rating property to Models/Movie.cs:

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

Tworzenie aplikacjiBuild the app

Ponieważ dodano nowe pole do Movie klasy, należy zaktualizować listę powiązań właściwości, aby ta nowa właściwość została uwzględniona.Because you've added a new field to the Movie class, you need to update the property binding list so this new property will be included. W programie MoviesController.cs zaktualizuj [Bind] atrybut dla obu Create metod i, Edit Aby uwzględnić Rating Właściwość:In MoviesController.cs, update the [Bind] attribute for both the Create and Edit action methods to include the Rating property:

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

Aktualizowanie szablonów widoku w celu wyświetlania, tworzenia i edytowania nowej Rating właściwości w widoku przeglądarki.Update the view templates in order to display, create, and edit the new Rating property in the browser view.

Edytuj plik /views/Movies/index.cshtml i Dodaj Rating pole:Edit the /Views/Movies/Index.cshtml file and add a Rating field:

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

Zaktualizuj /views/Movies/Create.cshtml z Rating polem.Update the /Views/Movies/Create.cshtml with a Rating field.

Możesz skopiować/wkleić poprzednią "grupę formularzy" i pozwól, aby funkcja intelliSense mogła zaktualizować pola.You can copy/paste the previous "form group" and let intelliSense help you update the fields. Technologia IntelliSense współpracuje z pomocnikami tagów.IntelliSense works with Tag Helpers.

Deweloper wpisze literę R dla wartości atrybutu ASP-for w drugim elemencie Label widoku.

Zaktualizuj pozostałe szablony.Update the remaining templates.

Zaktualizuj SeedData klasę, aby zapewnić wartość nowej kolumny.Update the SeedData class so that it provides a value for the new column. Poniżej przedstawiono przykładową zmianę, ale trzeba wprowadzić tę zmianę dla każdej z nich new Movie .A sample change is shown below, but you'll want to make this change for each new Movie.

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

Aplikacja nie będzie działała, dopóki baza danych nie zostanie zaktualizowana w celu uwzględnienia nowego pola.The app won't work until the DB is updated to include the new field. Jeśli jest teraz uruchomiona, SqlException zgłaszane są następujące elementy:If it's run now, the following SqlException is thrown:

SqlException: Invalid column name 'Rating'.

Ten błąd występuje, ponieważ zaktualizowana Klasa modelu filmu jest inna niż schemat tabeli filmów istniejącej bazy danych.This error occurs because the updated Movie model class is different than the schema of the Movie table of the existing database. (Brak Rating kolumn w tabeli bazy danych).(There's no Rating column in the database table.)

Istnieje kilka metod rozpoznawania błędu:There are a few approaches to resolving the error:

  1. Entity Framework automatycznie porzucić i ponownie utworzyć bazę danych na podstawie nowego schematu klasy modelu.Have the Entity Framework automatically drop and re-create the database based on the new model class schema. To podejście jest bardzo wygodne w cyklu rozwoju, gdy chodzi o aktywne programowanie w testowej bazie danych. pozwala ona szybko rozwijać model i schemat bazy danych.This approach is very convenient early in the development cycle when you're doing active development on a test database; it allows you to quickly evolve the model and database schema together. Minusem, mimo że utracisz istniejące dane w bazie danych, więc nie chcesz używać tego podejścia w produkcyjnej bazie danych.The downside, though, is that you lose existing data in the database — so you don't want to use this approach on a production database! Użycie inicjatora do automatycznego umieszczania bazy danych z danymi testowymi jest często wydajnym sposobem na tworzenie aplikacji.Using an initializer to automatically seed a database with test data is often a productive way to develop an application. Jest to dobre podejście do wczesnego programowania i korzystania z oprogramowania SQLite.This is a good approach for early development and when using SQLite.

  2. Jawnie zmodyfikuj schemat istniejącej bazy danych, tak aby pasował do klas modelu.Explicitly modify the schema of the existing database so that it matches the model classes. Zaletą tego podejścia jest utrzymywanie danych.The advantage of this approach is that you keep your data. Tę zmianę można wprowadzić ręcznie lub przez utworzenie skryptu zmiany bazy danych.You can make this change either manually or by creating a database change script.

  3. Użyj Migracje Code First, aby zaktualizować schemat bazy danych.Use Code First Migrations to update the database schema.

W tym samouczku zostanie użyta Migracje Code First.For this tutorial, Code First Migrations is used.

W menu Narzędzia wybierz kolejno pozycje menedżer pakietów NuGet > konsola Menedżera pakietów.From the Tools menu, select NuGet Package Manager > Package Manager Console.

Menu PMC

W obszarze PMC wprowadź następujące polecenia:In the PMC, enter the following commands:

Add-Migration Rating
Update-Database

Add-MigrationPolecenie informuje platformę migracji, aby przeanalizować bieżący Movie model z bieżącym Movie schematem bazy danych i utworzyć wymagany kod w celu przeprowadzenia migracji bazy danych do nowego modelu.The Add-Migration command tells the migration framework to examine the current Movie model with the current Movie DB schema and create the necessary code to migrate the DB to the new model.

Nazwa "Rating" jest arbitralna i jest używana do nazwy pliku migracji.The name "Rating" is arbitrary and is used to name the migration file. Warto użyć zrozumiałej nazwy dla pliku migracji.It's helpful to use a meaningful name for the migration file.

Jeśli wszystkie rekordy w bazie danych zostaną usunięte, metoda Initialize będzie wypełniać bazę danych i zawierać Rating pole.If all the records in the DB are deleted, the initialize method will seed the DB and include the Rating field.

Uruchom aplikację i sprawdź, czy można tworzyć, edytować i wyświetlać filmy z Rating polem.Run the app and verify you can create, edit, and display movies with a Rating field.