Część 4. Dodawanie modelu do aplikacji ASP.NET Core MVCPart 4, add a model to an ASP.NET Core MVC app

Autorzy Rick Anderson i Tomasz DykstraBy Rick Anderson and Tom Dykstra

W tej sekcji dodasz klasy do zarządzania filmami w bazie danych.In this section, you add classes for managing movies in a database. Te klasy będą częścią "m odelu" aplikacji m VC.These classes will be the "M odel" part of the M VC app.

Te klasy są używane z Entity Framework Core (Ef Core) do pracy z bazą danych.You use these classes with Entity Framework Core (EF Core) to work with a database. EF Core to struktura obiektu mapowania relacyjnego (ORM), która upraszcza kod dostępu do danych, który trzeba napisać.EF Core is an object-relational mapping (ORM) framework that simplifies the data access code that you have to write.

Klasy modelu, które tworzysz, są nazywane klasami POCO ( z Lain P LR o biekty), ponieważ nie mają żadnej zależności od EF Core.The model classes you create are known as POCO classes (from P lain O ld C LR O bjects) because they don't have any dependency on EF Core. Po prostu definiują właściwości danych, które będą przechowywane w bazie danych.They just define the properties of the data that will be stored in the database.

W tym samouczku najpierw napiszesz klasy modelu, a EF Core tworzy bazę danych.In this tutorial, you write the model classes first, and EF Core creates the database.

Dodaj klasę modelu danychAdd a data model class

Kliknij prawym przyciskiem myszy folder modele > Dodaj > klasę.Right-click the Models folder > Add > Class. Nazwij plik Movie.cs.Name the file Movie.cs.

Zaktualizuj plik Movie.cs przy użyciu następującego kodu:Update the Movie.cs file with the following code:

using System;
using System.ComponentModel.DataAnnotations;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int Id { get; set; }
        public string Title { get; set; }

        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}

MovieKlasa zawiera Id pole, które jest wymagane przez bazę danych klucza podstawowego.The Movie class contains an Id field, which is required by the database for the primary key.

DataTypeAtrybut on ReleaseDate określa typ danych ( Date ).The DataType attribute on ReleaseDate specifies the type of the data (Date). Z tym atrybutem:With this attribute:

  • Użytkownik nie musi wprowadzać informacji o czasie w polu Data.The user is not required to enter time information in the date field.
  • Tylko data jest wyświetlana, a nie informacje o czasie.Only the date is displayed, not time information.

Adnotacje DataAnnotations są omówione w kolejnym samouczku.DataAnnotations are covered in a later tutorial.

Dodawanie pakietów NuGetAdd NuGet packages

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

Menu PMC

W obszarze PMC Uruchom następujące polecenie:In the PMC, run the following command:

Install-Package Microsoft.EntityFrameworkCore.SqlServer

Poprzednie polecenie dodaje dostawcę SQL Server EF Core.The preceding command adds the EF Core SQL Server provider. Pakiet dostawcy instaluje pakiet EF Core jako zależność.The provider package installs the EF Core package as a dependency. Dodatkowe pakiety są instalowane automatycznie w kroku tworzenia szkieletu w dalszej części tego samouczka.Additional packages are installed automatically in the scaffolding step later in the tutorial.

Tworzenie klasy kontekstu bazy danychCreate a database context class

Klasa kontekstu bazy danych jest wymagana do koordynowania funkcji EF Core (tworzenie, odczytywanie, aktualizowanie, usuwanie) dla Movie modelu.A database context class is needed to coordinate EF Core functionality (Create, Read, Update, Delete) for the Movie model. Kontekst bazy danych pochodzi od Microsoft. EntityFrameworkCore. DbContext i określa jednostki, które mają zostać uwzględnione w modelu danych.The database context is derived from Microsoft.EntityFrameworkCore.DbContext and specifies the entities to include in the data model.

Utwórz folder danych .Create a Data folder.

Dodaj plik Data/MvcMovieContext. cs o następującym kodzie:Add a Data/MvcMovieContext.cs file with the following code:

using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;

namespace MvcMovie.Data
{
    public class MvcMovieContext : DbContext
    {
        public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
            : base(options)
        {
        }

        public DbSet<Movie> Movie { get; set; }
    }
}

Poprzedni kod tworzy właściwość nieogólnymi <Movie> dla zestawu jednostek.The preceding code creates a DbSet<Movie> property for the entity set. W Entity Framework terminologii zestaw jednostek zwykle odpowiada tabeli bazy danych.In Entity Framework terminology, an entity set typically corresponds to a database table. Jednostka odnosi się do wiersza w tabeli.An entity corresponds to a row in the table.

Rejestrowanie kontekstu bazy danychRegister the database context

ASP.NET Core jest skompilowany przy użyciu iniekcji zależności (di).ASP.NET Core is built with dependency injection (DI). Usługi (takie jak kontekst EF Core DB) muszą być zarejestrowane przy użyciu funkcji "DI" podczas uruchamiania aplikacji.Services (such as the EF Core DB context) must be registered with DI during application startup. Składniki wymagające tych usług (takie jak Razor strony) są udostępniane przez parametry konstruktora.Components that require these services (such as Razor Pages) are provided these services via constructor parameters. Kod konstruktora, który pobiera wystąpienie kontekstu bazy danych, jest wyświetlany w dalszej części tego samouczka.The constructor code that gets a DB context instance is shown later in the tutorial. W tej sekcji rejestrujesz kontekst bazy danych przy użyciu funkcji DI Container.In this section, you register the database context with the DI container.

Dodaj następujące using instrukcje w górnej części Startup.cs:Add the following using statements at the top of Startup.cs:

using MvcMovie.Data;
using Microsoft.EntityFrameworkCore;

Dodaj następujący wyróżniony kod w Startup.ConfigureServices :Add the following highlighted code in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    services.AddDbContext<MvcMovieContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

Nazwa parametrów połączenia jest przenoszona do kontekstu przez wywołanie metody w obiekcie DbContextOptions .The name of the connection string is passed in to the context by calling a method on a DbContextOptions object. W przypadku lokalnego projektowania system konfiguracji ASP.NET Core odczytuje parametry połączenia z appsettings.json pliku.For local development, the ASP.NET Core configuration system reads the connection string from the appsettings.json file.

Dodaj parametry połączenia z bazą danychAdd a database connection string

Dodaj parametry połączenia do appsettings.json pliku:Add a connection string to the appsettings.json file:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

Kompiluj projekt jako sprawdzenie błędów kompilatora.Build the project as a check for compiler errors.

Strony z filmem szkieletuScaffold movie pages

Użyj narzędzia do tworzenia szkieletu, aby utworzyć strony z przykładem tworzenie, odczytywanie, aktualizowanie i usuwanie (CRUD) dla modelu filmu.Use the scaffolding tool to produce Create, Read, Update, and Delete (CRUD) pages for the movie model.

W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder controllers , > Dodaj > nowy element szkieletowy.In Solution Explorer, right-click the Controllers folder > Add > New Scaffolded Item.

Widok powyżej kroku

W oknie dialogowym Dodawanie szkieletu wybierz pozycję kontroler MVC z widokami przy użyciu Entity Framework > Dodaj.In the Add Scaffold dialog, select MVC Controller with views, using Entity Framework > Add.

Okno dialogowe Dodawanie szkieletu

Ukończ okno dialogowe Dodawanie kontrolera :Complete the Add Controller dialog:

  • Model Class: Movie (MvcMovie. models)Model class: Movie (MvcMovie.Models)
  • Klasa kontekstu danych: MvcMovieContext (MvcMovie. Data)Data context class: MvcMovieContext (MvcMovie.Data)

Dodaj kontekst danych

  • Widoki: Zachowaj wartość domyślną dla każdej zaznaczonej opcjiViews: Keep the default of each option checked
  • Nazwa kontrolera: Zachowaj domyślną MoviesControllerController name: Keep the default MoviesController
  • Wybierz pozycję Dodaj.Select Add

Program Visual Studio tworzy:Visual Studio creates:

  • Kontroler filmów (controllers/MoviesController. cs)A movies controller (Controllers/MoviesController.cs)
  • Razor Wyświetlanie plików na potrzeby tworzenia, usuwania, szczegółów, edytowania i indeksowania stron (widoki/filmy/ * . cshtml)Razor view files for Create, Delete, Details, Edit, and Index pages (Views/Movies/*.cshtml)

Automatyczne tworzenie tych plików jest znane jako rusztowania.The automatic creation of these files is known as scaffolding.

Nie można jeszcze użyć stron szkieletowych, ponieważ baza danych nie istnieje.You can't use the scaffolded pages yet because the database doesn't exist. Jeśli uruchomisz aplikację i klikniesz link aplikacji filmowej , uzyskasz dostęp do otwartej bazy danych lub nie ma takiej tabeli: komunikat o błędzie filmu.If you run the app and click on the Movie App link, you get a Cannot open database or no such table: Movie error message.

Migracja początkowaInitial migration

Użyj funkcji migracji EF Core, aby utworzyć bazę danych.Use the EF Core Migrations feature to create the database. Migracje to zestaw narzędzi umożliwiających tworzenie i aktualizowanie bazy danych w celu dopasowania jej do modelu danych.Migrations is a set of tools that let you create and update a database to match your data model.

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

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

Add-Migration InitialCreate
Update-Database
  • Add-Migration InitialCreate: Generuje migrację/{timestamp} _InitialCreate. cs pliku migracji.Add-Migration InitialCreate: Generates a Migrations/{timestamp}_InitialCreate.cs migration file. InitialCreateArgument jest nazwą migracji.The InitialCreate argument is the migration name. Można użyć dowolnej nazwy, ale według Konwencji została wybrana nazwa opisująca migrację.Any name can be used, but by convention, a name is selected that describes the migration. Ponieważ jest to pierwsza migracja, wygenerowana Klasa zawiera kod, aby utworzyć schemat bazy danych.Because this is the first migration, the generated class contains code to create the database schema. Schemat bazy danych jest oparty na modelu określonym w MvcMovieContext klasie.The database schema is based on the model specified in the MvcMovieContext class.

  • Update-Database: Aktualizuje bazę danych do najnowszej migracji, która została utworzona przez poprzednie polecenie.Update-Database: Updates the database to the latest migration, which the previous command created. To polecenie uruchamia Up metodę w pliku migrations/{Time-sygnatura} _InitialCreate. cs , który tworzy bazę danych.This command runs the Up method in the Migrations/{time-stamp}_InitialCreate.cs file, which creates the database.

    Polecenie aktualizacji bazy danych generuje następujące ostrzeżenie:The database update command generates the following warning:

    Nie określono typu dla kolumny dziesiętnej "price" w typie jednostki "Movie".No type was specified for the decimal column 'Price' on entity type 'Movie'. Spowoduje to, że wartości powinny być obcinane w trybie dyskretnym, jeśli nie mieszczą się w domyślnej precyzji i skali.This will cause values to be silently truncated if they do not fit in the default precision and scale. Jawnie określ typ kolumny programu SQL Server, który może pomieścić wszystkie wartości przy użyciu "HasColumnType ()".Explicitly specify the SQL server column type that can accommodate all the values using 'HasColumnType()'.

    Możesz zignorować to ostrzeżenie. zostanie on rozwiązany w kolejnym samouczku.You can ignore that warning, it will be fixed in a later tutorial.

Aby uzyskać więcej informacji na temat narzędzi PMC dla EF Core, zobacz EF Core Tools Reference-PMC in Visual Studio.For more information on the PMC tools for EF Core, see EF Core tools reference - PMC in Visual Studio.

Klasa InitialCreateThe InitialCreate class

Przejrzyj migracje/{timestamp} _InitialCreate pliku migracji CS:Examine the Migrations/{timestamp}_InitialCreate.cs migration file:

public partial class InitialCreate : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Movie",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", 
                                 SqlServerValueGenerationStrategy.IdentityColumn),
                Title = table.Column<string>(nullable: true),
                ReleaseDate = table.Column<DateTime>(nullable: false),
                Genre = table.Column<string>(nullable: true),
                Price = table.Column<decimal>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Movie", x => x.Id);
            });
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "Movie");
    }
}

UpMetoda tworzy tabelę filmów i konfiguruje Id jako klucz podstawowy.The Up method creates the Movie table and configures Id as the primary key. DownMetoda przywraca zmiany schematu wykonane podczas Up migracji.The Down method reverts the schema changes made by the Up migration.

Testowanie aplikacjiTest the app

  • Uruchom aplikację i kliknij link aplikacji filmowej .Run the app and click the Movie App link.

    Jeśli zostanie wyświetlony wyjątek podobny do jednego z następujących:If you get an exception similar to one of the following:

SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.

Prawdopodobnie pominięto krok migracji.You probably missed the migrations step.

  • Przetestuj stronę Tworzenie .Test the Create page. Wprowadź i prześlij dane.Enter and submit data.

    Uwaga

    W polu nie można wprowadzać przecinków dziesiętnych Price .You may not be able to enter decimal commas in the Price field. Aby zapewnić obsługę walidacji jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i dla formatów nieUS-Englishych, aplikacja musi być globalna.To support jQuery validation for non-English locales that use a comma (",") for a decimal point and for non US-English date formats, the app must be globalized. Aby uzyskać instrukcje dotyczące globalizacji, zobacz ten problemw usłudze GitHub.For globalization instructions, see this GitHub issue.

  • Przetestuj strony Edytuj, szczegóły i Usuń .Test the Edit, Details, and Delete pages.

Wstrzykiwanie zależności w kontrolerzeDependency injection in the controller

Otwórz plik controllers/MoviesController. cs i zapoznaj się z konstruktorem:Open the Controllers/MoviesController.cs file and examine the constructor:

public class MoviesController : Controller
{
    private readonly MvcMovieContext _context;

    public MoviesController(MvcMovieContext context)
    {
        _context = context;
    }

Konstruktor używa iniekcji zależności do iniekcji kontekstu bazy danych ( MvcMovieContext ) do kontrolera.The constructor uses Dependency Injection to inject the database context (MvcMovieContext) into the controller. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.The database context is used in each of the CRUD methods in the controller.

Modele silnie wpisane i @model słowo kluczoweStrongly typed models and the @model keyword

Wcześniej w tym samouczku pokazano, jak kontroler może przekazać dane lub obiekty do widoku przy użyciu ViewData słownika.Earlier in this tutorial, you saw how a controller can pass data or objects to a view using the ViewData dictionary. ViewDataSłownik jest obiektem dynamicznym, który zapewnia wygodny, późny sposób przekazywania informacji do widoku.The ViewData dictionary is a dynamic object that provides a convenient late-bound way to pass information to a view.

MVC oferuje również możliwość przekazywania obiektów modelu silnie typu do widoku.MVC also provides the ability to pass strongly typed model objects to a view. Takie silnie wpisane podejście umożliwia sprawdzanie kodu czasu kompilacji.This strongly typed approach enables compile time code checking. Mechanizm tworzenia szkieletu używa tego podejścia (czyli przekazania silnie określonego modelu) z MoviesController klasą i widokami.The scaffolding mechanism used this approach (that is, passing a strongly typed model) with the MoviesController class and views.

Przejrzyj wygenerowaną Details metodę w pliku controllers/MoviesController. cs :Examine the generated Details method in the Controllers/MoviesController.cs file:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

idParametr jest zazwyczaj przesyłany jako dane trasy.The id parameter is generally passed as route data. Na przykład https://localhost:5001/movies/details/1 zestawy:For example https://localhost:5001/movies/details/1 sets:

  • Kontroler do movies kontrolera (pierwszy segment adresu URL).The controller to the movies controller (the first URL segment).
  • Akcja do details (drugi segment adresu URL).The action to details (the second URL segment).
  • Identyfikator 1 (ostatni segment adresu URL).The id to 1 (the last URL segment).

Można również przekazać id za pomocą ciągu zapytania w następujący sposób:You can also pass in the id with a query string as follows:

https://localhost:5001/movies/details?id=1

idParametr jest zdefiniowany jako typ dopuszczający wartość null ( int? ) w przypadku, gdy nie podano wartości identyfikatora.The id parameter is defined as a nullable type (int?) in case an ID value isn't provided.

Wyrażenie lambda jest przesyłane do, FirstOrDefaultAsync Aby wybrać jednostki filmu, które pasują do wartości danych trasy lub ciągu zapytania.A lambda expression is passed in to FirstOrDefaultAsync to select movie entities that match the route data or query string value.

var movie = await _context.Movie
    .FirstOrDefaultAsync(m => m.Id == id);

Jeśli film zostanie znaleziony, wystąpienie Movie modelu jest przesyłane do Details widoku:If a movie is found, an instance of the Movie model is passed to the Details view:

return View(movie);

Zapoznaj się z zawartością pliku widoki/filmy/szczegóły. cshtml :Examine the contents of the Views/Movies/Details.cshtml file:

@model MvcMovie.Models.Movie

@{
    ViewData["Title"] = "Details";
}

<h1>Details</h1>

<div>
    <h4>Movie</h4>
    <hr />
    <dl class="row">
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Title)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Title)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.ReleaseDate)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.ReleaseDate)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Genre)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Genre)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Price)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Price)
        </dd>
    </dl>
</div>
<div>
    <a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
    <a asp-action="Index">Back to List</a>
</div>

@modelInstrukcja w górnej części pliku widoku określa typ obiektu, który jest oczekiwany przez widok.The @model statement at the top of the view file specifies the type of object that the view expects. Po utworzeniu kontrolera filmu @model uwzględniono następujące instrukcje:When the movie controller was created, the following @model statement was included:

@model MvcMovie.Models.Movie

Ta @model dyrektywa zezwala na dostęp do filmu, który kontroler przeszedł do widoku.This @model directive allows access to the movie that the controller passed to the view. ModelObiekt ma silną wartość.The Model object is strongly typed. Na przykład w widoku details. cshtml kod przekazuje każde pole filmu do DisplayNameFor DisplayFor pomocników HTML z obiektem o jednoznacznie określonym typie Model .For example, in the Details.cshtml view, the code passes each movie field to the DisplayNameFor and DisplayFor HTML Helpers with the strongly typed Model object. CreateMetody i Edit i widoki również przekazują Movie obiekt modelu.The Create and Edit methods and views also pass a Movie model object.

Sprawdź widok index. cshtml i Index metodę w kontrolerze filmów.Examine the Index.cshtml view and the Index method in the Movies controller. Zwróć uwagę, jak kod tworzy List obiekt, gdy wywołuje View metodę.Notice how the code creates a List object when it calls the View method. Kod przekazuje tę Movies listę z Index metody akcji do widoku:The code passes this Movies list from the Index action method to the view:

// GET: Movies
public async Task<IActionResult> Index()
{
    return View(await _context.Movie.ToListAsync());
}

Gdy kontroler filmów został utworzony, szkielet zawiera następujące @model instrukcje w górnej części pliku index. cshtml :When the movies controller was created, scaffolding included the following @model statement at the top of the Index.cshtml file:

@model IEnumerable<MvcMovie.Models.Movie>

@modelDyrektywa pozwala uzyskać dostęp do listy filmów przekazaną przez kontroler do widoku przy użyciu Model jednoznacznie określonego obiektu.The @model directive allows you to access the list of movies that the controller passed to the view by using a Model object that's strongly typed. Na przykład w widoku index. cshtml kod przechodzi przez filmy z foreach instrukcją względem obiektu silnie wpisanego Model :For example, in the Index.cshtml view, the code loops through the movies with a foreach statement over the strongly typed Model object:

@model IEnumerable<MvcMovie.Models.Movie>

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Title)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ReleaseDate)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Genre)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Price)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@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>
                <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>

Ponieważ Model obiekt jest silnie określony (jako IEnumerable<Movie> obiekt), każdy element w pętli jest wpisywany jako Movie .Because the Model object is strongly typed (as an IEnumerable<Movie> object), each item in the loop is typed as Movie. Dzięki temu możesz uzyskać kontrolę czasu kompilowania kodu.Among other benefits, this means that you get compile time checking of the code.

Dodatkowe zasobyAdditional resources

Dodaj klasę modelu danychAdd a data model class

Kliknij prawym przyciskiem myszy folder modele > Dodaj > klasę.Right-click the Models folder > Add > Class. Nazwij plik Movie.cs.Name the file Movie.cs.

Zaktualizuj plik Movie.cs przy użyciu następującego kodu:Update the Movie.cs file with the following code:

using System;
using System.ComponentModel.DataAnnotations;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int Id { get; set; }
        public string Title { get; set; }

        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}

MovieKlasa zawiera Id pole, które jest wymagane przez bazę danych klucza podstawowego.The Movie class contains an Id field, which is required by the database for the primary key.

DataTypeAtrybut on ReleaseDate określa typ danych ( Date ).The DataType attribute on ReleaseDate specifies the type of the data (Date). Z tym atrybutem:With this attribute:

  • Użytkownik nie musi wprowadzać informacji o czasie w polu Data.The user is not required to enter time information in the date field.
  • Tylko data jest wyświetlana, a nie informacje o czasie.Only the date is displayed, not time information.

Adnotacje DataAnnotations są omówione w kolejnym samouczku.DataAnnotations are covered in a later tutorial.

Dodawanie pakietów NuGetAdd NuGet packages

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

Menu PMC

W obszarze PMC Uruchom następujące polecenie:In the PMC, run the following command:

Install-Package Microsoft.EntityFrameworkCore.SqlServer

Poprzednie polecenie dodaje dostawcę SQL Server EF Core.The preceding command adds the EF Core SQL Server provider. Pakiet dostawcy instaluje pakiet EF Core jako zależność.The provider package installs the EF Core package as a dependency. Dodatkowe pakiety są instalowane automatycznie w kroku tworzenia szkieletu w dalszej części tego samouczka.Additional packages are installed automatically in the scaffolding step later in the tutorial.

Tworzenie klasy kontekstu bazy danychCreate a database context class

Klasa kontekstu bazy danych jest wymagana do koordynowania funkcji EF Core (tworzenie, odczytywanie, aktualizowanie, usuwanie) dla Movie modelu.A database context class is needed to coordinate EF Core functionality (Create, Read, Update, Delete) for the Movie model. Kontekst bazy danych pochodzi od Microsoft. EntityFrameworkCore. DbContext i określa jednostki, które mają zostać uwzględnione w modelu danych.The database context is derived from Microsoft.EntityFrameworkCore.DbContext and specifies the entities to include in the data model.

Utwórz folder danych .Create a Data folder.

Dodaj plik Data/MvcMovieContext. cs o następującym kodzie:Add a Data/MvcMovieContext.cs file with the following code:

using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;

namespace MvcMovie.Data
{
    public class MvcMovieContext : DbContext
    {
        public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
            : base(options)
        {
        }

        public DbSet<Movie> Movie { get; set; }
    }
}

Poprzedni kod tworzy właściwość nieogólnymi <Movie> dla zestawu jednostek.The preceding code creates a DbSet<Movie> property for the entity set. W Entity Framework terminologii zestaw jednostek zwykle odpowiada tabeli bazy danych.In Entity Framework terminology, an entity set typically corresponds to a database table. Jednostka odnosi się do wiersza w tabeli.An entity corresponds to a row in the table.

Rejestrowanie kontekstu bazy danychRegister the database context

ASP.NET Core jest skompilowany przy użyciu iniekcji zależności (di).ASP.NET Core is built with dependency injection (DI). Usługi (takie jak kontekst EF Core DB) muszą być zarejestrowane przy użyciu funkcji "DI" podczas uruchamiania aplikacji.Services (such as the EF Core DB context) must be registered with DI during application startup. Składniki wymagające tych usług (takie jak Razor strony) są udostępniane przez parametry konstruktora.Components that require these services (such as Razor Pages) are provided these services via constructor parameters. Kod konstruktora, który pobiera wystąpienie kontekstu bazy danych, jest wyświetlany w dalszej części tego samouczka.The constructor code that gets a DB context instance is shown later in the tutorial. W tej sekcji rejestrujesz kontekst bazy danych przy użyciu funkcji DI Container.In this section, you register the database context with the DI container.

Dodaj następujące using instrukcje w górnej części Startup.cs:Add the following using statements at the top of Startup.cs:

using MvcMovie.Data;
using Microsoft.EntityFrameworkCore;

Dodaj następujący wyróżniony kod w Startup.ConfigureServices :Add the following highlighted code in Startup.ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();

    services.AddDbContext<MvcMovieContext>(options =>
            options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

Nazwa parametrów połączenia jest przenoszona do kontekstu przez wywołanie metody w obiekcie DbContextOptions .The name of the connection string is passed in to the context by calling a method on a DbContextOptions object. W przypadku lokalnego projektowania system konfiguracji ASP.NET Core odczytuje parametry połączenia z appsettings.json pliku.For local development, the ASP.NET Core configuration system reads the connection string from the appsettings.json file.

Dodaj parametry połączenia z bazą danychAdd a database connection string

Dodaj parametry połączenia do appsettings.json pliku:Add a connection string to the appsettings.json file:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

Kompiluj projekt jako sprawdzenie błędów kompilatora.Build the project as a check for compiler errors.

Strony z filmem szkieletuScaffold movie pages

Użyj narzędzia do tworzenia szkieletu, aby utworzyć strony z przykładem tworzenie, odczytywanie, aktualizowanie i usuwanie (CRUD) dla modelu filmu.Use the scaffolding tool to produce Create, Read, Update, and Delete (CRUD) pages for the movie model.

W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder controllers , > Dodaj > nowy element szkieletowy.In Solution Explorer, right-click the Controllers folder > Add > New Scaffolded Item.

Widok powyżej kroku

W oknie dialogowym Dodawanie szkieletu wybierz pozycję kontroler MVC z widokami przy użyciu Entity Framework > Dodaj.In the Add Scaffold dialog, select MVC Controller with views, using Entity Framework > Add.

Okno dialogowe Dodawanie szkieletu

Ukończ okno dialogowe Dodawanie kontrolera :Complete the Add Controller dialog:

  • Model Class: Movie (MvcMovie. models)Model class: Movie (MvcMovie.Models)
  • Klasa kontekstu danych: MvcMovieContext (MvcMovie. Data)Data context class: MvcMovieContext (MvcMovie.Data)

Dodaj kontekst danych

  • Widoki: Zachowaj wartość domyślną dla każdej zaznaczonej opcjiViews: Keep the default of each option checked
  • Nazwa kontrolera: Zachowaj domyślną MoviesControllerController name: Keep the default MoviesController
  • Wybierz pozycję Dodaj.Select Add

Program Visual Studio tworzy:Visual Studio creates:

  • Kontroler filmów (controllers/MoviesController. cs)A movies controller (Controllers/MoviesController.cs)
  • Razor Wyświetlanie plików na potrzeby tworzenia, usuwania, szczegółów, edytowania i indeksowania stron (widoki/filmy/ * . cshtml)Razor view files for Create, Delete, Details, Edit, and Index pages (Views/Movies/*.cshtml)

Automatyczne tworzenie tych plików jest znane jako rusztowania.The automatic creation of these files is known as scaffolding.

Nie można jeszcze użyć stron szkieletowych, ponieważ baza danych nie istnieje.You can't use the scaffolded pages yet because the database doesn't exist. Jeśli uruchomisz aplikację i klikniesz link aplikacji filmowej , uzyskasz dostęp do otwartej bazy danych lub nie ma takiej tabeli: komunikat o błędzie filmu.If you run the app and click on the Movie App link, you get a Cannot open database or no such table: Movie error message.

Migracja początkowaInitial migration

Użyj funkcji migracji EF Core, aby utworzyć bazę danych.Use the EF Core Migrations feature to create the database. Migracje to zestaw narzędzi umożliwiających tworzenie i aktualizowanie bazy danych w celu dopasowania jej do modelu danych.Migrations is a set of tools that let you create and update a database to match your data model.

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

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

Add-Migration InitialCreate
Update-Database
  • Add-Migration InitialCreate: Generuje migrację/{timestamp} _InitialCreate. cs pliku migracji.Add-Migration InitialCreate: Generates a Migrations/{timestamp}_InitialCreate.cs migration file. InitialCreateArgument jest nazwą migracji.The InitialCreate argument is the migration name. Można użyć dowolnej nazwy, ale według Konwencji została wybrana nazwa opisująca migrację.Any name can be used, but by convention, a name is selected that describes the migration. Ponieważ jest to pierwsza migracja, wygenerowana Klasa zawiera kod, aby utworzyć schemat bazy danych.Because this is the first migration, the generated class contains code to create the database schema. Schemat bazy danych jest oparty na modelu określonym w MvcMovieContext klasie.The database schema is based on the model specified in the MvcMovieContext class.

  • Update-Database: Aktualizuje bazę danych do najnowszej migracji, która została utworzona przez poprzednie polecenie.Update-Database: Updates the database to the latest migration, which the previous command created. To polecenie uruchamia Up metodę w pliku migrations/{Time-sygnatura} _InitialCreate. cs , który tworzy bazę danych.This command runs the Up method in the Migrations/{time-stamp}_InitialCreate.cs file, which creates the database.

    Polecenie aktualizacji bazy danych generuje następujące ostrzeżenie:The database update command generates the following warning:

    Nie określono typu dla kolumny dziesiętnej "price" w typie jednostki "Movie".No type was specified for the decimal column 'Price' on entity type 'Movie'. Spowoduje to, że wartości powinny być obcinane w trybie dyskretnym, jeśli nie mieszczą się w domyślnej precyzji i skali.This will cause values to be silently truncated if they do not fit in the default precision and scale. Jawnie określ typ kolumny programu SQL Server, który może pomieścić wszystkie wartości przy użyciu "HasColumnType ()".Explicitly specify the SQL server column type that can accommodate all the values using 'HasColumnType()'.

    Możesz zignorować to ostrzeżenie. zostanie on rozwiązany w kolejnym samouczku.You can ignore that warning, it will be fixed in a later tutorial.

Aby uzyskać więcej informacji na temat narzędzi PMC dla EF Core, zobacz EF Core Tools Reference-PMC in Visual Studio.For more information on the PMC tools for EF Core, see EF Core tools reference - PMC in Visual Studio.

Klasa InitialCreateThe InitialCreate class

Przejrzyj migracje/{timestamp} _InitialCreate pliku migracji CS:Examine the Migrations/{timestamp}_InitialCreate.cs migration file:

public partial class InitialCreate : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Movie",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("SqlServer:ValueGenerationStrategy", 
                                 SqlServerValueGenerationStrategy.IdentityColumn),
                Title = table.Column<string>(nullable: true),
                ReleaseDate = table.Column<DateTime>(nullable: false),
                Genre = table.Column<string>(nullable: true),
                Price = table.Column<decimal>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Movie", x => x.Id);
            });
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "Movie");
    }
}

UpMetoda tworzy tabelę filmów i konfiguruje Id jako klucz podstawowy.The Up method creates the Movie table and configures Id as the primary key. DownMetoda przywraca zmiany schematu wykonane podczas Up migracji.The Down method reverts the schema changes made by the Up migration.

Testowanie aplikacjiTest the app

  • Uruchom aplikację i kliknij link aplikacji filmowej .Run the app and click the Movie App link.

    Jeśli zostanie wyświetlony wyjątek podobny do jednego z następujących:If you get an exception similar to one of the following:

SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.

Prawdopodobnie pominięto krok migracji.You probably missed the migrations step.

  • Przetestuj stronę Tworzenie .Test the Create page. Wprowadź i prześlij dane.Enter and submit data.

    Uwaga

    W polu nie można wprowadzać przecinków dziesiętnych Price .You may not be able to enter decimal commas in the Price field. Aby zapewnić obsługę walidacji jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i dla formatów nieUS-Englishych, aplikacja musi być globalna.To support jQuery validation for non-English locales that use a comma (",") for a decimal point and for non US-English date formats, the app must be globalized. Aby uzyskać instrukcje dotyczące globalizacji, zobacz ten problemw usłudze GitHub.For globalization instructions, see this GitHub issue.

  • Przetestuj strony Edytuj, szczegóły i Usuń .Test the Edit, Details, and Delete pages.

Wstrzykiwanie zależności w kontrolerzeDependency injection in the controller

Otwórz plik controllers/MoviesController. cs i zapoznaj się z konstruktorem:Open the Controllers/MoviesController.cs file and examine the constructor:

public class MoviesController : Controller
{
    private readonly MvcMovieContext _context;

    public MoviesController(MvcMovieContext context)
    {
        _context = context;
    }

Konstruktor używa iniekcji zależności do iniekcji kontekstu bazy danych ( MvcMovieContext ) do kontrolera.The constructor uses Dependency Injection to inject the database context (MvcMovieContext) into the controller. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.The database context is used in each of the CRUD methods in the controller.

Modele silnie wpisane i @model słowo kluczoweStrongly typed models and the @model keyword

Wcześniej w tym samouczku pokazano, jak kontroler może przekazać dane lub obiekty do widoku przy użyciu ViewData słownika.Earlier in this tutorial, you saw how a controller can pass data or objects to a view using the ViewData dictionary. ViewDataSłownik jest obiektem dynamicznym, który zapewnia wygodny, późny sposób przekazywania informacji do widoku.The ViewData dictionary is a dynamic object that provides a convenient late-bound way to pass information to a view.

MVC oferuje również możliwość przekazywania obiektów modelu silnie typu do widoku.MVC also provides the ability to pass strongly typed model objects to a view. Takie silnie wpisane podejście umożliwia sprawdzanie kodu czasu kompilacji.This strongly typed approach enables compile time code checking. Mechanizm tworzenia szkieletu używa tego podejścia (czyli przekazania silnie określonego modelu) z MoviesController klasą i widokami.The scaffolding mechanism used this approach (that is, passing a strongly typed model) with the MoviesController class and views.

Przejrzyj wygenerowaną Details metodę w pliku controllers/MoviesController. cs :Examine the generated Details method in the Controllers/MoviesController.cs file:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

idParametr jest zazwyczaj przesyłany jako dane trasy.The id parameter is generally passed as route data. Na przykład https://localhost:5001/movies/details/1 zestawy:For example https://localhost:5001/movies/details/1 sets:

  • Kontroler do movies kontrolera (pierwszy segment adresu URL).The controller to the movies controller (the first URL segment).
  • Akcja do details (drugi segment adresu URL).The action to details (the second URL segment).
  • Identyfikator 1 (ostatni segment adresu URL).The id to 1 (the last URL segment).

Można również przekazać id za pomocą ciągu zapytania w następujący sposób:You can also pass in the id with a query string as follows:

https://localhost:5001/movies/details?id=1

idParametr jest zdefiniowany jako typ dopuszczający wartość null ( int? ) w przypadku, gdy nie podano wartości identyfikatora.The id parameter is defined as a nullable type (int?) in case an ID value isn't provided.

Wyrażenie lambda jest przesyłane do, FirstOrDefaultAsync Aby wybrać jednostki filmu, które pasują do wartości danych trasy lub ciągu zapytania.A lambda expression is passed in to FirstOrDefaultAsync to select movie entities that match the route data or query string value.

var movie = await _context.Movie
    .FirstOrDefaultAsync(m => m.Id == id);

Jeśli film zostanie znaleziony, wystąpienie Movie modelu jest przesyłane do Details widoku:If a movie is found, an instance of the Movie model is passed to the Details view:

return View(movie);

Zapoznaj się z zawartością pliku widoki/filmy/szczegóły. cshtml :Examine the contents of the Views/Movies/Details.cshtml file:

@model MvcMovie.Models.Movie

@{
    ViewData["Title"] = "Details";
}

<h1>Details</h1>

<div>
    <h4>Movie</h4>
    <hr />
    <dl class="row">
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Title)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Title)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.ReleaseDate)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.ReleaseDate)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Genre)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Genre)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Price)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Price)
        </dd>
    </dl>
</div>
<div>
    <a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
    <a asp-action="Index">Back to List</a>
</div>

@modelInstrukcja w górnej części pliku widoku określa typ obiektu, który jest oczekiwany przez widok.The @model statement at the top of the view file specifies the type of object that the view expects. Po utworzeniu kontrolera filmu @model uwzględniono następujące instrukcje:When the movie controller was created, the following @model statement was included:

@model MvcMovie.Models.Movie

Ta @model dyrektywa zezwala na dostęp do filmu, który kontroler przeszedł do widoku.This @model directive allows access to the movie that the controller passed to the view. ModelObiekt ma silną wartość.The Model object is strongly typed. Na przykład w widoku details. cshtml kod przekazuje każde pole filmu do DisplayNameFor DisplayFor pomocników HTML z obiektem o jednoznacznie określonym typie Model .For example, in the Details.cshtml view, the code passes each movie field to the DisplayNameFor and DisplayFor HTML Helpers with the strongly typed Model object. CreateMetody i Edit i widoki również przekazują Movie obiekt modelu.The Create and Edit methods and views also pass a Movie model object.

Sprawdź widok index. cshtml i Index metodę w kontrolerze filmów.Examine the Index.cshtml view and the Index method in the Movies controller. Zwróć uwagę, jak kod tworzy List obiekt, gdy wywołuje View metodę.Notice how the code creates a List object when it calls the View method. Kod przekazuje tę Movies listę z Index metody akcji do widoku:The code passes this Movies list from the Index action method to the view:

// GET: Movies
public async Task<IActionResult> Index()
{
    return View(await _context.Movie.ToListAsync());
}

Gdy kontroler filmów został utworzony, szkielet zawiera następujące @model instrukcje w górnej części pliku index. cshtml :When the movies controller was created, scaffolding included the following @model statement at the top of the Index.cshtml file:

@model IEnumerable<MvcMovie.Models.Movie>

@modelDyrektywa pozwala uzyskać dostęp do listy filmów przekazaną przez kontroler do widoku przy użyciu Model jednoznacznie określonego obiektu.The @model directive allows you to access the list of movies that the controller passed to the view by using a Model object that's strongly typed. Na przykład w widoku index. cshtml kod przechodzi przez filmy z foreach instrukcją względem obiektu silnie wpisanego Model :For example, in the Index.cshtml view, the code loops through the movies with a foreach statement over the strongly typed Model object:

@model IEnumerable<MvcMovie.Models.Movie>

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Title)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ReleaseDate)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Genre)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Price)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@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>
                <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>

Ponieważ Model obiekt jest silnie określony (jako IEnumerable<Movie> obiekt), każdy element w pętli jest wpisywany jako Movie .Because the Model object is strongly typed (as an IEnumerable<Movie> object), each item in the loop is typed as Movie. Dzięki temu możesz uzyskać kontrolę czasu kompilowania kodu.Among other benefits, this means that you get compile time checking of the code.

Dodatkowe zasobyAdditional resources

Dodaj klasę modelu danychAdd a data model class

Kliknij prawym przyciskiem myszy folder modele > Dodaj > klasę.Right-click the Models folder > Add > Class. Nazwij film klasy.Name the class Movie.

Dodaj następujące właściwości do Movie klasy:Add the following properties to the Movie class:

using System;
using System.ComponentModel.DataAnnotations;

namespace MvcMovie.Models
{
    public class Movie
    {
        public int Id { get; set; }
        public string Title { get; set; }

        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
}

MovieKlasa zawiera:The Movie class contains:

  • IdPole, które jest wymagane przez bazę danych dla klucza podstawowego.The Id field which is required by the database for the primary key.

  • [DataType(DataType.Date)]: Atrybut DataType określa typ danych ( Date ).[DataType(DataType.Date)]: The DataType attribute specifies the type of the data (Date). Z tym atrybutem:With this attribute:

    • Użytkownik nie musi wprowadzać informacji o czasie w polu Data.The user is not required to enter time information in the date field.
    • Tylko data jest wyświetlana, a nie informacje o czasie.Only the date is displayed, not time information.

Adnotacje DataAnnotations są omówione w kolejnym samouczku.DataAnnotations are covered in a later tutorial.

Tworzenie szkieletu modelu filmuScaffold the movie model

W tej sekcji model filmu jest szkieletem.In this section, the movie model is scaffolded. Oznacza to, że narzędzie tworzenia szkieletów tworzy strony dla operacji Create, Read, Update i Delete (CRUD) dla modelu filmu.That is, the scaffolding tool produces pages for Create, Read, Update, and Delete (CRUD) operations for the movie model.

W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder controllers , > Dodaj > nowy element szkieletowy.In Solution Explorer, right-click the Controllers folder > Add > New Scaffolded Item.

Widok powyżej kroku

W oknie dialogowym Dodawanie szkieletu wybierz pozycję kontroler MVC z widokami przy użyciu Entity Framework > Dodaj.In the Add Scaffold dialog, select MVC Controller with views, using Entity Framework > Add.

Okno dialogowe Dodawanie szkieletu

Ukończ okno dialogowe Dodawanie kontrolera :Complete the Add Controller dialog:

  • Model Class: Movie (MvcMovie. models)Model class: Movie (MvcMovie.Models)
  • Klasa kontekstu danych: Wybierz + ikonę i Dodaj domyślną MvcMovie. models. MvcMovieContextData context class: Select the + icon and add the default MvcMovie.Models.MvcMovieContext

Dodaj kontekst danych

  • Widoki: Zachowaj wartość domyślną dla każdej zaznaczonej opcjiViews: Keep the default of each option checked
  • Nazwa kontrolera: Zachowaj domyślną MoviesControllerController name: Keep the default MoviesController
  • Wybierz pozycję Dodaj.Select Add

Okno dialogowe Dodawanie kontrolera

Program Visual Studio tworzy:Visual Studio creates:

  • Klasa kontekstu bazy danych Entity Framework Core (Data/MvcMovieContext. cs)An Entity Framework Core database context class (Data/MvcMovieContext.cs)
  • Kontroler filmów (controllers/MoviesController. cs)A movies controller (Controllers/MoviesController.cs)
  • Razor Wyświetlanie plików na potrzeby tworzenia, usuwania, szczegółów, edytowania i indeksowania stron (widoki/filmy/ * . cshtml)Razor view files for Create, Delete, Details, Edit, and Index pages (Views/Movies/*.cshtml)

Automatyczne tworzenie kontekstu bazy danych i metod akcji CRUD (tworzenie, odczytywanie, aktualizowanie i usuwanie) jest znane jako rusztowanie.The automatic creation of the database context and CRUD (create, read, update, and delete) action methods and views is known as scaffolding.

Jeśli uruchomisz aplikację i klikniesz link do filmu MVC , zostanie wyświetlony komunikat o błędzie podobny do następującego:If you run the app and click on the Mvc Movie link, you get an error similar to the following:

An unhandled exception occurred while processing the request.

SqlException: Cannot open database "MvcMovieContext-<GUID removed>" requested by the login. The login failed.
Login failed for user 'Rick'.

System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString

Należy utworzyć bazę danych i użyć funkcji migracji EF Core, aby to zrobić.You need to create the database, and you use the EF Core Migrations feature to do that. Migracja umożliwia utworzenie bazy danych zgodnej z modelem danych i zaktualizowanie schematu bazy danych, gdy zmieni się model danych.Migrations lets you create a database that matches your data model and update the database schema when your data model changes.

Migracja początkowaInitial migration

W tej sekcji zostały wykonane następujące zadania:In this section, the following tasks are completed:

  • Dodawanie początkowej migracji.Add an initial migration.
  • Zaktualizuj bazę danych przy użyciu początkowej migracji.Update the database with the initial migration.
  1. W menu Narzędzia wybierz kolejno pozycje Menedżer pakietów NuGet > konsola Menedżera pakietów (PMC).From the Tools menu, select NuGet Package Manager > Package Manager Console (PMC).

    Menu PMC

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

    Add-Migration Initial
    Update-Database
    

    Add-MigrationPolecenie generuje kod, aby utworzyć początkowy schemat bazy danych.The Add-Migration command generates code to create the initial database schema.

    Schemat bazy danych jest oparty na modelu określonym w MvcMovieContext klasie.The database schema is based on the model specified in the MvcMovieContext class. InitialArgument jest nazwą migracji.The Initial argument is the migration name. Można użyć dowolnej nazwy, ale według Konwencji, nazwy opisującej migrację.Any name can be used, but by convention, a name that describes the migration is used. Aby uzyskać więcej informacji, zobacz Samouczek 5. stosowanie migracji do przykładowej firmy Contoso University.For more information, see Samouczek 5. stosowanie migracji do przykładowej firmy Contoso University.

    Update-DatabasePolecenie uruchamia Up metodę w pliku migrations/{Time-sygnatura} _InitialCreate. cs , który tworzy bazę danych.The Update-Database command runs the Up method in the Migrations/{time-stamp}_InitialCreate.cs file, which creates the database.

Sprawdzanie kontekstu zarejestrowanego przy iniekcji zależnościExamine the context registered with dependency injection

ASP.NET Core jest skompilowany przy użyciu iniekcji zależności (di).ASP.NET Core is built with dependency injection (DI). Usługi (takie jak kontekst EF Core DB) są rejestrowane przy użyciu funkcji "DI" podczas uruchamiania aplikacji.Services (such as the EF Core DB context) are registered with DI during application startup. Składniki wymagające tych usług (takie jak Razor strony) są udostępniane przez parametry konstruktora.Components that require these services (such as Razor Pages) are provided these services via constructor parameters. Kod konstruktora, który pobiera wystąpienie kontekstu bazy danych, jest wyświetlany w dalszej części tego samouczka.The constructor code that gets a DB context instance is shown later in the tutorial.

Narzędzie do tworzenia szkieletów automatycznie utworzyło kontekst bazy danych i zarejestrował go przy użyciu DI kontenera.The scaffolding tool automatically created a DB context and registered it with the DI container.

Przeanalizuj poniższą Startup.ConfigureServices metodę.Examine the following Startup.ConfigureServices method. Podświetlony wiersz został dodany przez program do tworzenia szkieletu:The highlighted line was added by the scaffolder:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies 
        // is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });


    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    services.AddDbContext<MvcMovieContext>(options =>
         options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

MvcMovieContextWspółrzędne EF Core funkcje (tworzenie, Odczyt, aktualizowanie, usuwanie itp.) dla Movie modelu.The MvcMovieContext coordinates EF Core functionality (Create, Read, Update, Delete, etc.) for the Movie model. Kontekst danych ( MvcMovieContext ) pochodzi od Microsoft. EntityFrameworkCore. DbContext.The data context (MvcMovieContext) is derived from Microsoft.EntityFrameworkCore.DbContext. Kontekst danych określa, które jednostki są uwzględnione w modelu danych:The data context specifies which entities are included in the data model:

// Unused usings removed.
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;  // Enables public DbSet<Movie> Movie

namespace MvcMovie.Data
{
    public class MvcMovieContext : DbContext
    {
        public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
            : base(options)
        {
        }

        public DbSet<Movie> Movie { get; set; }
    }
}

Poprzedni kod tworzy właściwość nieogólnymi <Movie> dla zestawu jednostek.The preceding code creates a DbSet<Movie> property for the entity set. W Entity Framework terminologii zestaw jednostek zwykle odpowiada tabeli bazy danych.In Entity Framework terminology, an entity set typically corresponds to a database table. Jednostka odnosi się do wiersza w tabeli.An entity corresponds to a row in the table.

Nazwa parametrów połączenia jest przenoszona do kontekstu przez wywołanie metody w obiekcie DbContextOptions .The name of the connection string is passed in to the context by calling a method on a DbContextOptions object. W przypadku lokalnego projektowania system konfiguracji ASP.NET Core odczytuje parametry połączenia z appsettings.json pliku.For local development, the ASP.NET Core configuration system reads the connection string from the appsettings.json file.

Testowanie aplikacjiTest the app

  • Uruchom aplikację i Dołącz /Movies do adresu URL w przeglądarce ( http://localhost:port/movies ).Run the app and append /Movies to the URL in the browser (http://localhost:port/movies).

Jeśli zostanie wyświetlony wyjątek bazy danych podobny do poniższego:If you get a database exception similar to the following:

SqlException: Cannot open database "MvcMovieContext-GUID" requested by the login. The login failed.
Login failed for user 'User-name'.

Pominięto krok migracji.You missed the migrations step.

  • Przetestuj link tworzenia .Test the Create link. Wprowadź i prześlij dane.Enter and submit data.

    Uwaga

    W polu nie można wprowadzać przecinków dziesiętnych Price .You may not be able to enter decimal commas in the Price field. Aby zapewnić obsługę walidacji jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i dla formatów nieUS-Englishych, aplikacja musi być globalna.To support jQuery validation for non-English locales that use a comma (",") for a decimal point and for non US-English date formats, the app must be globalized. Aby uzyskać instrukcje dotyczące globalizacji, zobacz ten problemw usłudze GitHub.For globalization instructions, see this GitHub issue.

  • Przetestuj linki Edytuj, Szczegóły i Usuń.Test the Edit, Details, and Delete links.

Zapoznaj się z Startup klasą:Examine the Startup class:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        // This lambda determines whether user consent for non-essential cookies 
        // is needed for a given request.
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });


    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    services.AddDbContext<MvcMovieContext>(options =>
         options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}

Poprzedni wyróżniony kod pokazuje kontekst bazy danych filmu dodawany do kontenera iniekcji zależności :The preceding highlighted code shows the movie database context being added to the Dependency Injection container:

  • services.AddDbContext<MvcMovieContext>(options => Określa bazę danych, która ma być używana, oraz parametry połączenia.services.AddDbContext<MvcMovieContext>(options => specifies the database to use and the connection string.
  • => jest operatorem lambda=> is a lambda operator

Otwórz plik controllers/MoviesController. cs i zapoznaj się z konstruktorem:Open the Controllers/MoviesController.cs file and examine the constructor:

public class MoviesController : Controller
{
    private readonly MvcMovieContext _context;

    public MoviesController(MvcMovieContext context)
    {
        _context = context;
    }

Konstruktor używa iniekcji zależności do iniekcji kontekstu bazy danych ( MvcMovieContext ) do kontrolera.The constructor uses Dependency Injection to inject the database context (MvcMovieContext) into the controller. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.The database context is used in each of the CRUD methods in the controller.

Modele silnie wpisane i @model słowo kluczoweStrongly typed models and the @model keyword

Wcześniej w tym samouczku pokazano, jak kontroler może przekazać dane lub obiekty do widoku przy użyciu ViewData słownika.Earlier in this tutorial, you saw how a controller can pass data or objects to a view using the ViewData dictionary. ViewDataSłownik jest obiektem dynamicznym, który zapewnia wygodny, późny sposób przekazywania informacji do widoku.The ViewData dictionary is a dynamic object that provides a convenient late-bound way to pass information to a view.

MVC oferuje również możliwość przekazywania obiektów modelu silnie typu do widoku.MVC also provides the ability to pass strongly typed model objects to a view. Takie silnie wpisane podejście umożliwia lepsze sprawdzanie czasu kompilowania kodu.This strongly typed approach enables better compile time checking of your code. Mechanizm tworzenia szkieletów korzysta z tego podejścia (czyli przekazywania modelu silnie określonego typu) z MoviesController klasą i widokami, gdy utworzyły metody i widoki.The scaffolding mechanism used this approach (that is, passing a strongly typed model) with the MoviesController class and views when it created the methods and views.

Przejrzyj wygenerowaną Details metodę w pliku controllers/MoviesController. cs :Examine the generated Details method in the Controllers/MoviesController.cs file:

// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    var movie = await _context.Movie
        .FirstOrDefaultAsync(m => m.Id == id);
    if (movie == null)
    {
        return NotFound();
    }

    return View(movie);
}

idParametr jest zazwyczaj przesyłany jako dane trasy.The id parameter is generally passed as route data. Na przykład https://localhost:5001/movies/details/1 zestawy:For example https://localhost:5001/movies/details/1 sets:

  • Kontroler do movies kontrolera (pierwszy segment adresu URL).The controller to the movies controller (the first URL segment).
  • Akcja do details (drugi segment adresu URL).The action to details (the second URL segment).
  • Identyfikator 1 (ostatni segment adresu URL).The id to 1 (the last URL segment).

Można również przekazać id za pomocą ciągu zapytania w następujący sposób:You can also pass in the id with a query string as follows:

https://localhost:5001/movies/details?id=1

idParametr jest zdefiniowany jako typ dopuszczający wartość null ( int? ) w przypadku, gdy nie podano wartości identyfikatora.The id parameter is defined as a nullable type (int?) in case an ID value isn't provided.

Wyrażenie lambda jest przesyłane do, FirstOrDefaultAsync Aby wybrać jednostki filmu, które pasują do wartości danych trasy lub ciągu zapytania.A lambda expression is passed in to FirstOrDefaultAsync to select movie entities that match the route data or query string value.

var movie = await _context.Movie
    .FirstOrDefaultAsync(m => m.Id == id);

Jeśli film zostanie znaleziony, wystąpienie Movie modelu jest przesyłane do Details widoku:If a movie is found, an instance of the Movie model is passed to the Details view:

return View(movie);

Zapoznaj się z zawartością pliku widoki/filmy/szczegóły. cshtml :Examine the contents of the Views/Movies/Details.cshtml file:

@model MvcMovie.Models.Movie

@{
    ViewData["Title"] = "Details";
}

<h1>Details</h1>

<div>
    <h4>Movie</h4>
    <hr />
    <dl class="row">
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Title)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Title)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.ReleaseDate)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.ReleaseDate)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Genre)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Genre)
        </dd>
        <dt class="col-sm-2">
            @Html.DisplayNameFor(model => model.Price)
        </dt>
        <dd class="col-sm-10">
            @Html.DisplayFor(model => model.Price)
        </dd>
    </dl>
</div>
<div>
    <a asp-action="Edit" asp-route-id="@Model.Id">Edit</a> |
    <a asp-action="Index">Back to List</a>
</div>

Dołączając @model instrukcję w górnej części pliku widoku, można określić typ obiektu, którego oczekuje widok.By including a @model statement at the top of the view file, you can specify the type of object that the view expects. Po utworzeniu kontrolera filmu Poniższa @model instrukcja została automatycznie uwzględniona w górnej części pliku details. cshtml :When you created the movie controller, the following @model statement was automatically included at the top of the Details.cshtml file:

@model MvcMovie.Models.Movie

Ta @model dyrektywa pozwala uzyskać dostęp do filmu, który kontroler przeszedł do widoku przy użyciu Model jednoznacznie określonego obiektu.This @model directive allows you to access the movie that the controller passed to the view by using a Model object that's strongly typed. Na przykład w widoku details. cshtml kod przekazuje każde pole filmu do DisplayNameFor DisplayFor pomocników HTML z obiektem o jednoznacznie określonym typie Model .For example, in the Details.cshtml view, the code passes each movie field to the DisplayNameFor and DisplayFor HTML Helpers with the strongly typed Model object. CreateMetody i Edit i widoki również przekazują Movie obiekt modelu.The Create and Edit methods and views also pass a Movie model object.

Sprawdź widok index. cshtml i Index metodę w kontrolerze filmów.Examine the Index.cshtml view and the Index method in the Movies controller. Zwróć uwagę, jak kod tworzy List obiekt, gdy wywołuje View metodę.Notice how the code creates a List object when it calls the View method. Kod przekazuje tę Movies listę z Index metody akcji do widoku:The code passes this Movies list from the Index action method to the view:

// GET: Movies
public async Task<IActionResult> Index()
{
    return View(await _context.Movie.ToListAsync());
}

Podczas tworzenia kontrolera filmów zostanie automatycznie uwzględniona następująca @model instrukcja w górnej części pliku index. cshtml :When you created the movies controller, scaffolding automatically included the following @model statement at the top of the Index.cshtml file:

@model IEnumerable<MvcMovie.Models.Movie>

@modelDyrektywa pozwala uzyskać dostęp do listy filmów przekazaną przez kontroler do widoku przy użyciu Model jednoznacznie określonego obiektu.The @model directive allows you to access the list of movies that the controller passed to the view by using a Model object that's strongly typed. Na przykład w widoku index. cshtml kod przechodzi przez filmy z foreach instrukcją względem obiektu silnie wpisanego Model :For example, in the Index.cshtml view, the code loops through the movies with a foreach statement over the strongly typed Model object:

@model IEnumerable<MvcMovie.Models.Movie>

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-action="Create">Create New</a>
</p>
<table class="table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Title)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.ReleaseDate)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Genre)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Price)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@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>
                <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>

Ponieważ Model obiekt jest silnie określony (jako IEnumerable<Movie> obiekt), każdy element w pętli jest wpisywany jako Movie .Because the Model object is strongly typed (as an IEnumerable<Movie> object), each item in the loop is typed as Movie. Dzięki temu możesz uzyskać kontrolę czasu kompilowania kodu:Among other benefits, this means that you get compile time checking of the code:

Dodatkowe zasobyAdditional resources