Deel 4: een model toevoegen aan een ASP.NET Core MVC-app
Notitie
Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikelvoor de huidige release.
Waarschuwing
Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie de .NET- en .NET Core-ondersteuningsbeleidvoor meer informatie. Zie de .NET 9-versie van dit artikelvoor de huidige release.
Belangrijk
Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.
Zie de .NET 9-versie van dit artikelvoor de huidige release.
Door Rick Anderson en Jon P Smith.
In deze handleiding worden klassen toegevoegd om films in een database te beheren. Deze klassen zijn het onderdeel 'Model' van de MVC-app.
Deze modelklassen worden gebruikt met Entity Framework Core (EF Core) om met een database te werken. EF Core is een ORM-framework (object-relational mapping) dat de code voor gegevenstoegang vereenvoudigt die u moet schrijven.
De gemaakte modelklassen worden POCO--klassen genoemd, van Plain Old CLR-Objects. POCO-klassen hebben geen afhankelijkheid van EF Core. Ze definiëren alleen de eigenschappen van de gegevens die moeten worden opgeslagen in de database.
In deze zelfstudie worden eerst modelklassen gemaakt en EF Core de database maakt.
Een gegevensmodelklasse toevoegen
Klik met de rechtermuisknop op de map Modellen>>Klassetoevoegen. Geef het bestand de naam Movie.cs
.
Werk het Models/Movie.cs
-bestand bij met de volgende code:
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; }
}
De klasse Movie
bevat een Id
veld, dat vereist is voor de database voor de primaire sleutel.
Het kenmerk DataType op ReleaseDate
geeft het type gegevens (Date
) aan. Met dit kenmerk:
- De gebruiker hoeft geen tijdgegevens in te voeren in het datumveld.
- Alleen de datum wordt weergegeven, geen tijdinformatie.
DataAnnotations worden behandeld in een volgende handleiding.
Het vraagteken na string
geeft aan dat de eigenschap nullable is. Voor meer informatie, zie Nullbare referentietypen.
NuGet-pakketten toevoegen
Visual Studio installeert automatisch de vereiste pakketten.
Bouw het project als controle op compilerfouten.
Filmpagina's opzetten
Gebruik het scaffolding hulpprogramma om de Create
-, Read
-, Update
- en Delete
-pagina's (CRUD) voor het filmmodel te produceren.
Klik in Solution Explorermet de rechtermuisknop op de map Controllers en selecteer Add > New Scaffolded Item.
In het dialoogvenster Nieuw gescaffolde item toevoegen:
- Selecteer in het linkerdeelvenster >Common>MVC-geïnstalleerd.
- Selecteer MVC-controller met weergaven met behulp van Entity Framework.
- Selecteer toevoegen.
Voltooi de MVC-controller toevoegen met weergaven, met behulp van het dialoogvenster Entity Framework:
- Selecteer in de vervolgkeuzelijst Modelklasse de optie Movie (MvcMovie.Models).
- Selecteer in de gegevenscontextklasse rij het + (plusteken).
- In het dialoogvenster Gegevenscontext toevoegen wordt de klassenaam MvcMovie.Data.MvcMovieContext gegenereerd.
- Selecteer toevoegen.
- Selecteer in de vervolgkeuzelijst Database providerSQL Server.
- Weergaven en Controllernaam: behoud de Standaardwaarde.
- Selecteer toevoegen.
Als u een foutbericht krijgt, selecteert u een tweede keer toevoegen om het opnieuw te proberen.
Met scaffolding worden de volgende pakketten toegevoegd:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
Met scaffolding maakt u het volgende:
- Een filmscontroller:
Controllers/MoviesController.cs
-
Razor bestanden weergeven voor maken, verwijderen, details, bewerken en pagina's indexeren:
Views/Movies/*.cshtml
- Een databasecontextklasse:
Data/MvcMovieContext.cs
De scaffolding werkt het volgende bij:
- Voegt vereiste pakketverwijzingen in het
MvcMovie.csproj
projectbestand in. - Registreert de databasecontext in het
Program.cs
-bestand. - Hiermee voegt u een databaseverbindingsreeks toe aan het
appsettings.json
-bestand.
Het automatisch maken van deze bestanden en bestandsupdates wordt bekend als scaffolding.
De pagina's in de scaffolded kunnen nog niet worden gebruikt omdat de database niet bestaat. Het uitvoeren van de app en het selecteren van de Film-app koppeling resulteert in een Kan de database niet openen of geen dergelijke tabel: Film foutbericht.
Bouw de app om te controleren of er geen fouten zijn.
Initiële migratie
Gebruik de functie EF CoreMigrations om de database te maken. Migrations is een set hulpprogramma's waarmee een database wordt gemaakt en bijgewerkt zodat deze overeenkomt met het gegevensmodel.
Selecteer in het menu ToolsNuGet Package Manager>Package Manager Console.
Voer in de Package Manager Console (PMC) de volgende opdracht in:
Add-Migration InitialCreate
-
Add-Migration InitialCreate
: genereert eenMigrations/{timestamp}_InitialCreate.cs
migratiebestand. Het argumentInitialCreate
is de migratienaam. Elke naam kan worden gebruikt, maar volgens de conventie wordt een naam geselecteerd die de migratie beschrijft. Omdat dit de eerste migratie is, bevat de gegenereerde klasse code om het databaseschema te maken. Het databaseschema is gebaseerd op het model dat is opgegeven in de klasseMvcMovieContext
.
De volgende waarschuwing wordt weergegeven, die in een latere stap wordt behandeld:
Er is geen winkeltype opgegeven voor de decimale eigenschap 'Prijs' voor entiteitstype 'Film'. Hierdoor worden waarden stilzwijgend afgekapt als ze niet in de standaardprecisie en schaal passen. Geef expliciet het kolomtype sql-server op dat alle waarden in 'OnModelCreating' kan bevatten met behulp van HasColumnType, geef precisie en schaal op met behulp van HasPrecision of configureer een waardeconversieprogramma met hasconversion.
Voer in de PMC de volgende opdracht in:
Update-Database
-
Update-Database
: hiermee wordt de database bijgewerkt naar de meest recente migratie, die met de vorige opdracht is gemaakt. Met deze opdracht wordt de methodeUp
uitgevoerd in hetMigrations/{time-stamp}_InitialCreate.cs
-bestand, waarmee de database wordt gemaakt.
Zie EF Core referentiemateriaal voor hulpprogramma's - PMC in Visual Studiovoor meer informatie over de PMC-hulpprogramma's voor EF Core.
De app testen
Voer de app uit en selecteer de koppeling Movie App.
Als u een uitzondering krijgt die vergelijkbaar is met het volgende, hebt u mogelijk het Update-Database
-commando gemist in stap van de-migraties:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Notitie
Mogelijk kunt u geen decimale komma's invoeren in het veld Price
. Ter ondersteuning van jQuery-validatie voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en voor niet-US-English datumnotaties, moet de app worden geglobaliseerd. Zie dit GitHub-probleemvoor instructies voor globalisatie.
De gegenereerde databasecontextklasse en -registratie onderzoeken
Met EF Corewordt gegevenstoegang uitgevoerd met behulp van een model. Een model bestaat uit entiteitsklassen en een contextobject dat een sessie met de database vertegenwoordigt. Met het contextobject kunt u gegevens opvragen en opslaan. De databasecontext is afgeleid van Microsoft.EntityFrameworkCore.DbContext en geeft de entiteiten op die moeten worden opgenomen in het gegevensmodel.
Met scaffolding wordt de contextklasse van de Data/MvcMovieContext.cs
database gemaakt:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;
namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}
public DbSet<MvcMovie.Models.Movie> Movie { get; set; } = default!;
}
}
Met de voorgaande code maakt u een eigenschap DbSet<Movie> die de films in de database vertegenwoordigt.
Afhankelijkheidsinjectie
ASP.NET Core is gebouwd met dependency injection (DI). Services, zoals de databasecontext, worden geregistreerd bij DI in Program.cs
. Deze services worden aangeboden aan componenten die ze nodig hebben via constructorparameters.
In het bestand Controllers/MoviesController.cs
gebruikt de constructor afhankelijkheidsinjectie om de MvcMovieContext
databasecontext in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Scaffolding heeft de volgende gemarkeerde code gegenereerd in Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext") ?? throw new InvalidOperationException("Connection string 'MvcMovieContext' not found.")));
Het ASP.NET Core-configuratiesysteem leest de verbindingsreeks van de database 'MvcMovieContext'.
De gegenereerde databaseverbindingsreeks onderzoeken
Scaffolding heeft een verbindingsreeks toegevoegd aan het appsettings.json
-bestand:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-4ebefa10-de29-4dea-b2ad-8a8dc6bcf374;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Voor lokale ontwikkeling leest het ASP.NET Core-configuratiesysteem de sleutel ConnectionString
uit het bestand appsettings.json
.
De InitialCreate
-klasse
Bekijk het Migrations/{timestamp}_InitialCreate.cs
migratiebestand:
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
In de voorgaande code:
-
InitialCreate.Up
maakt de filmtabel en configureertId
als primaire sleutel. -
InitialCreate.Down
de schemawijzigingen die door deUp
migratie zijn aangebracht, terugdraaien.
Afhankelijkheidsinjectie in de controller
Open het bestand Controllers/MoviesController.cs
en bekijk de constructor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
De constructor gebruikt afhankelijkheidsinjectie om de databasecontext (MvcMovieContext
) in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Test de pagina maken. Voer gegevens in en verzend deze.
Test de bewerken, detailsen pagina's verwijderen.
Sterk getypte modellen en de @model
richtlijn
Eerder in deze zelfstudie hebt u gezien hoe een controller gegevens of objecten aan een weergave kan doorgeven met behulp van de ViewData
woordenlijst. De ViewData
woordenlijst is een dynamisch object dat een handige, laat-gebonden manier biedt om informatie door te geven aan een weergave.
MVC biedt de mogelijkheid tot het doorgeven van sterk getypte modelobjecten aan een weergave. Deze sterk getypeerde benadering maakt controle van code tijdens de compileertijd mogelijk. Het steigermechanisme heeft een sterk getypeerd model doorgegeven in de MoviesController
klasse en weergaven.
Bekijk de gegenereerde methode Details
in het bestand Controllers/MoviesController.cs
:
// 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);
}
De parameter id
wordt over het algemeen doorgegeven als routegegevens. Bijvoorbeeld https://localhost:5001/movies/details/1
reeksen:
- De controller voor de
movies
-controller, het eerste URL-segment. - De actie voor
details
, het tweede URL-segment. - Het
id
tot 1, het laatste URL-segment.
De id
kan worden doorgegeven met een querystring, zoals in het volgende voorbeeld:
https://localhost:5001/movies/details?id=1
De parameter id
wordt gedefinieerd als een nullable type (int?
) in gevallen waarin de id
waarde niet is opgegeven.
Een lambda-expressie wordt doorgegeven aan de methode FirstOrDefaultAsync om filmentiteiten te selecteren die overeenkomen met de routegegevens of querytekenreekswaarde.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Als er een film wordt gevonden, wordt een exemplaar van het Movie
model doorgegeven aan de Details
weergave:
return View(movie);
Bekijk de inhoud van het Views/Movies/Details.cshtml
-bestand:
@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>
De @model
-instructie boven aan het weergavebestand geeft het type object op dat door de weergave wordt verwacht. Toen de filmcontroller werd gemaakt, werd de volgende @model
instructie opgenomen:
@model MvcMovie.Models.Movie
Deze @model
richtlijn geeft toegang tot de film die door de controller aan de weergave is doorgegeven. Het Model
-object is sterk getypt. In de Details.cshtml
-weergave geeft de code bijvoorbeeld elk filmveld door aan de DisplayNameFor
- en DisplayFor
-HTML-helpers met het sterk getypeerde Model
-object. De Create
en Edit
methoden en weergaven geven ook een Movie
modelobject door.
Bekijk de Index.cshtml
-weergave en de methode Index
in de controller Films. U ziet hoe de code een List
-object maakt wanneer deze de methode View
aanroept. De code geeft deze Movies
lijst door vanuit de actiemethode Index
aan de weergave:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
De code retourneert probleemdetails als de eigenschap Movie
van de gegevenscontext null is.
Toen de filmcontroller werd gemaakt, bevatte scaffolding de volgende @model
instructie bovenaan het Index.cshtml
-bestand.
@model IEnumerable<MvcMovie.Models.Movie>
De @model
-instructie maakt toegang mogelijk tot de lijst met films die de controller aan de weergave heeft doorgegeven door gebruik te maken van een sterk getypt Model
-object. In de weergave Index.cshtml
doorloopt de code bijvoorbeeld de films met een foreach
-instructie over het sterk getypte 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>
Omdat het Model
-object sterk is getypt als een IEnumerable<Movie>
-object, wordt elk item in de lus getypt als Movie
. De compiler valideert onder andere de typen die in de code worden gebruikt.
Aanvullende informatiebronnen
In deze handleiding worden klassen toegevoegd voor het beheren van films in een database. Deze klassen zijn het onderdeel 'Model' van de MVC-app.
Deze modelklassen worden gebruikt met Entity Framework Core (EF Core) om met een database te werken. EF Core is een ORM-framework (object-relational mapping) dat de code voor gegevenstoegang vereenvoudigt die u moet schrijven.
De modelklassen die zijn gemaakt, staan bekend als POCO--klassen, afgeleid van Plain Old CLR Objects. POCO-klassen hebben geen afhankelijkheid van EF Core. Ze definiëren alleen de eigenschappen van de gegevens die moeten worden opgeslagen in de database.
In deze zelfstudie worden eerst modelklassen gemaakt en EF Core de database maakt.
Een gegevensmodelklasse toevoegen
Klik met de rechtermuisknop op de map Modellen>>Klassetoevoegen. Geef het bestand de naam Movie.cs
.
Werk het Models/Movie.cs
-bestand bij met de volgende code:
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; }
}
De klasse Movie
bevat een Id
veld, dat vereist is voor de database voor de primaire sleutel.
Het kenmerk DataType op ReleaseDate
geeft het type gegevens (Date
) aan. Met dit kenmerk:
- De gebruiker hoeft geen tijdgegevens in te voeren in het datumveld.
- Alleen de datum wordt weergegeven, geen tijdinformatie.
DataAnnotations worden besproken in een latere handleiding.
Het vraagteken na string
geeft aan dat de eigenschap nullable is. Zie Null-verwijzingstypenvoor meer informatie.
NuGet-pakketten toevoegen
Visual Studio installeert automatisch de vereiste pakketten.
Bouw het project als controle op compilerfouten.
Filmpagina's opzetten
Gebruik de tool om Create
, Read
, Update
, en Delete
-pagina's (CRUD) voor het filmmodel te maken.
Klik in Solution Explorermet de rechtermuisknop op de map Controllers en selecteer Add > New Scaffolded Item.
In het dialoogvenster Nieuw Ondersteund Item Toevoegen:
- Selecteer in het linkerdeelvenster >Common>MVC-geïnstalleerd.
- Selecteer MVC-controller met weergaven met behulp van Entity Framework.
- Selecteer toevoegen.
Voltooi de MVC-controller toevoegen met weergaven, met behulp van het dialoogvenster Entity Framework:
- Selecteer in de vervolgkeuzelijst van de Modelklasse , Movie (MvcMovie.Models).
- Selecteer in de rij van de gegevenscontextklasse het + (plusteken).
- In het dialoogvenster Gegevenscontext toevoegen wordt de klassenaam MvcMovie.Data.MvcMovieContext gegenereerd.
- Selecteer toevoegen.
- Selecteer in de vervolgkeuzelijst DatabaseproviderSQL Server-.
- Weergaven en Controllernaam: behoud de standaardwaarde.
- Selecteer toevoegen.
Als u een foutbericht krijgt, selecteert u een tweede keer toevoegen om het opnieuw te proberen.
Met scaffolding worden de volgende pakketten toegevoegd:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
Met scaffolding maakt u het volgende:
- Een filmscontroller:
Controllers/MoviesController.cs
-
Razor bestanden weergeven voor maken, verwijderen, details, bewerken en pagina's indexeren:
Views/Movies/*.cshtml
- Een databasecontextklasse:
Data/MvcMovieContext.cs
Scaffolding werkt het volgende bij:
- Voegt vereiste pakketverwijzingen in het
MvcMovie.csproj
projectbestand in. - Registreert de databasecontext in het
Program.cs
-bestand. - Hiermee voegt u een databaseverbindingsreeks toe aan het
appsettings.json
-bestand.
Het automatisch maken van deze bestanden en bestandsupdates wordt genoemd.
De pagina's in de scaffolded kunnen nog niet worden gebruikt omdat de database niet bestaat. Het uitvoeren van de app en het selecteren van de Film-app koppeling resulteert in een Kan de database niet openen of geen dergelijke tabel: Film foutbericht.
Bouw de app om te controleren of er geen fouten zijn.
Initiële migratie
Gebruik de functie EF CoreMigrations om de database te maken. Migrations is een set hulpprogramma's waarmee een database wordt gemaakt en bijgewerkt zodat deze overeenkomt met het gegevensmodel.
Selecteer in het menu ToolsNuGet Package Manager>Package Manager Console.
Voer in de Package Manager Console (PMC) de volgende opdrachten in:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: genereert eenMigrations/{timestamp}_InitialCreate.cs
migratiebestand. Het argumentInitialCreate
is de migratienaam. Elke naam kan worden gebruikt, maar volgens de conventie wordt een naam geselecteerd die de migratie beschrijft. Omdat dit de eerste migratie is, bevat de gegenereerde klasse code om het databaseschema te maken. Het databaseschema is gebaseerd op het model dat is opgegeven in de klasseMvcMovieContext
.Update-Database
: hiermee wordt de database bijgewerkt naar de meest recente migratie, die met de vorige opdracht is gemaakt. Met deze opdracht wordt de methodeUp
uitgevoerd in hetMigrations/{time-stamp}_InitialCreate.cs
-bestand, waarmee de database wordt gemaakt.
Met de opdracht Update-Database
wordt de volgende waarschuwing gegenereerd:
Er is geen winkeltype opgegeven voor de decimale eigenschap 'Prijs' voor entiteitstype 'Film'. Hierdoor worden waarden stilzwijgend afgekapt als ze niet in de standaardprecisie en schaal passen. Geef expliciet het kolomtype sql-server op dat alle waarden in 'OnModelCreating' kan bevatten met behulp van HasColumnType, geef precisie en schaal op met behulp van HasPrecision of configureer een waardeconversieprogramma met hasconversion.
Negeer de voorgaande waarschuwing. Deze is opgelost in een latere zelfstudie.
Voor meer informatie over de PMC-hulpprogramma's voor EF Core, zie het referentiemateriaal voor EF Core - PMC in Visual Studio.
De app testen
Voer de app uit en selecteer de koppeling Movie App.
Als u een uitzondering krijgt die vergelijkbaar is met de volgende, dan hebt u mogelijk het Update-Database
-commando gemist in migratiestap .
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Notitie
Mogelijk kunt u geen decimale komma's invoeren in het veld Price
. Ter ondersteuning van jQuery-validatie voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en voor niet-US-English datumnotaties, moet de app worden geglobaliseerd. Zie dit GitHub-probleemvoor instructies voor globalisatie.
De gegenereerde databasecontextklasse en -registratie onderzoeken
Met EF Corewordt gegevenstoegang uitgevoerd met behulp van een model. Een model bestaat uit entiteitsklassen en een contextobject dat een sessie met de database vertegenwoordigt. Met het contextobject kunt u gegevens opvragen en opslaan. De databasecontext is afgeleid van Microsoft.EntityFrameworkCore.DbContext en geeft de entiteiten op die moeten worden opgenomen in het gegevensmodel.
Met scaffolding wordt de contextklasse van de database Data/MvcMovieContext.cs
gemaakt.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;
namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}
public DbSet<MvcMovie.Models.Movie> Movie { get; set; }
}
}
Met de voorgaande code maakt u een eigenschap DbSet<Movie> die de films in de database vertegenwoordigt.
Afhankelijkheidsinjectie
ASP.NET Core maakt gebruik van afhankelijkheidsinjectie (DI). Services, zoals de databasecontext, worden geregistreerd bij DI in Program.cs
. Deze services worden via constructorparameters geleverd aan componenten die ze vereisen.
In het bestand Controllers/MoviesController.cs
gebruikt de constructor afhankelijkheidsinjectie om de MvcMovieContext
databasecontext in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Scaffolding heeft de volgende gemarkeerde code gegenereerd in Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
Het ASP.NET Core-configuratiesysteem leest de verbindingsreeks van de database 'MvcMovieContext'.
De gegenereerde databaseverbindingsreeks onderzoeken
Scaffolding heeft een verbindingsreeks toegevoegd aan het appsettings.json
-bestand:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Data Source=MvcMovieContext-ea7a4069-f366-4742-bd1c-3f753a804ce1.db"
}
}
Voor lokale ontwikkeling leest het ASP.NET Core-configuratiesysteem de ConnectionString
sleutel uit het appsettings.json
-bestand leest.
De InitialCreate
-klasse
Bekijk het Migrations/{timestamp}_InitialCreate.cs
migratiebestand:
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
In de voorgaande code:
-
InitialCreate.Up
maakt de filmtabel en configureertId
als primaire sleutel. -
InitialCreate.Down
de schemawijzigingen die door deUp
migratie zijn aangebracht, terugdraaien.
Afhankelijkheidsinjectie in de controller
Open het bestand Controllers/MoviesController.cs
en bekijk de constructor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
De constructor gebruikt afhankelijkheidsinjectie om de databasecontext (MvcMovieContext
) in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Test de pagina Maak. Voer gegevens in en verzend deze.
Test de bewerken, detailsen pagina's verwijderen.
Sterk getypte modellen en de @model
richtlijn
Eerder in deze zelfstudie hebt u gezien hoe een controller gegevens of objecten aan een weergave kan doorgeven met behulp van de ViewData
woordenlijst. De ViewData
woordenlijst is een dynamisch object dat een handige, laat-gebonden manier biedt om informatie door te geven aan een weergave.
MVC biedt de mogelijkheid om sterk getypte modelobjecten door te geven aan een view. Deze sterk getypeerde benadering maakt controle tijdens de compilatietijd mogelijk. Het scaffoldingmechanisme heeft een sterk getypeerd model doorgegeven in de MoviesController
-klasse en view-componenten.
Bekijk de gegenereerde methode Details
in het bestand Controllers/MoviesController.cs
:
// 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);
}
De parameter id
wordt over het algemeen doorgegeven als routegegevens. Bijvoorbeeld https://localhost:5001/movies/details/1
sets:
- De koppeling naar de
movies
-controller, het eerste URL-segment. - De actie voor
details
, het tweede URL-segment. - Het
id
tot 1, het laatste URL-segment.
De id
kan worden doorgegeven met een queryreeks, zoals in het onderstaande voorbeeld.
https://localhost:5001/movies/details?id=1
De parameter id
wordt gedefinieerd als een nullable type (int?
) in gevallen waarin de id
waarde niet is opgegeven.
Een lambda-expressie wordt doorgegeven aan de methode FirstOrDefaultAsync om filmentiteiten te selecteren die overeenkomen met de routegegevens of querytekenreekswaarde.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Als er een film wordt gevonden, wordt een exemplaar van het Movie
model doorgegeven aan de Details
weergave:
return View(movie);
Bekijk de inhoud van het Views/Movies/Details.cshtml
-bestand:
@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>
De @model
-instructie boven aan het weergavebestand geeft het type object op dat door de weergave wordt verwacht. Toen de filmcontroller werd gemaakt, werd de volgende @model
instructie opgenomen:
@model MvcMovie.Models.Movie
Deze @model
instructie geeft toegang tot de film die de controller heeft doorgegeven aan de weergave. Het Model
-object is strikt getypeerd. In de weergave Details.cshtml
geeft de code bijvoorbeeld elk filmveld door aan de DisplayNameFor
en DisplayFor
HTML Helpers met het sterk getypte Model
-object. De Create
en Edit
methoden en weergaven geven ook een Movie
modelobject door.
Bekijk de Index.cshtml
-weergave en de methode Index
in de controller Films. U ziet hoe de code een List
-object maakt wanneer deze de methode View
aanroept. De code geeft deze Movies
lijst door vanuit de actiemethode Index
aan de weergave:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
De code retourneert probleemdetails als de eigenschap Movie
van de gegevenscontext null is.
Toen de filmcontroller werd gemaakt, bevatte scaffolding de volgende @model
instructie boven aan het Index.cshtml
-bestand:
@model IEnumerable<MvcMovie.Models.Movie>
De @model
-instructie biedt toegang tot de lijst met films die de controller aan de weergave heeft doorgegeven met behulp van een Model
-object dat sterk getypt is. In de Index.cshtml
-weergave doorloopt de code bijvoorbeeld de films met een foreach
-instructie over het sterk getypte 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>
Omdat het Model
-object sterk is getypt als een IEnumerable<Movie>
-object, wordt elk item in de lus getypt als Movie
. De compiler valideert onder andere de typen die in de code worden gebruikt.
Aanvullende informatiebronnen
In deze handleiding worden klassen toegevoegd voor het beheren van films in een database. Deze klassen vormen het 'Model'-deel van de MVC-app.
Deze modelklassen worden gebruikt met Entity Framework Core (EF Core) om met een database te werken. EF Core is een ORM-framework (object-relational mapping) dat de code voor gegevenstoegang vereenvoudigt die u moet schrijven.
De gemaakte modelklassen worden POCO--klassen genoemd, van Plain Old CLR Objects. POCO-klassen hebben geen afhankelijkheid van EF Core. Ze definiëren alleen de eigenschappen van de gegevens die moeten worden opgeslagen in de database.
In deze zelfstudie worden eerst modelklassen gemaakt en EF Core de database maakt.
Een gegevensmodelklasse toevoegen
Klik met de rechtermuisknop op de map Modellen>>Klassetoevoegen. Geef het bestand de naam Movie.cs
.
Werk het Models/Movie.cs
-bestand bij met de volgende code:
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; }
}
De klasse Movie
bevat een Id
veld, dat vereist is voor de database voor de primaire sleutel.
Het kenmerk DataType op ReleaseDate
geeft het type gegevens (Date
) aan. Met dit kenmerk:
- De gebruiker hoeft geen tijdgegevens in te voeren in het datumveld.
- Alleen de datum wordt weergegeven, geen tijdinformatie.
DataAnnotations worden besproken in een latere handleiding.
Het vraagteken na string
geeft aan dat de eigenschap nullable is. Zie Null-verwijzingstypenvoor meer informatie.
NuGet-pakketten toevoegen
Visual Studio installeert automatisch de vereiste pakketten.
Bouw het project als controle op compilerfouten.
Filmpagina's van scaffold
Gebruik het scaffolding-hulpmiddel om Create
-, Read
-, Update
- en Delete
-pagina's (CRUD) te ontwikkelen voor het filmmodel.
Klik in Solution Explorermet de rechtermuisknop op de map Controllers en selecteer Add > New Scaffolded Item.
In het dialoogvenster Nieuw Gestructureerd Item Toevoegen:
- Selecteer in het linkerdeelvenster geïnstalleerd>Common>MVC.
- Selecteer MVC-controller met weergaveopties met behulp van Entity Framework.
- Selecteer toevoegen.
Voltooi de MVC-controller toevoegen met weergaven, met behulp van het dialoogvenster Entity Framework:
- Selecteer in de vervolgkeuzelijst Modelklasse, de optie Movie (MvcMovie.Models).
- Selecteer in de gegevenscontextklasse rij het + (plusteken).
- In het dialoogvenster Gegevenscontext toevoegen wordt de klassenaam MvcMovie.Data.MvcMovieContext gegenereerd.
- Selecteer toevoegen.
- Selecteer in de vervolgkeuzelijst Databaseprovider de optie SQL Server.
- weergaven en controllernaam: standaard houden.
- Selecteer toevoegen.
Als u een foutbericht krijgt, selecteert u een tweede keer toevoegen om het opnieuw te proberen.
Met scaffolding worden de volgende pakketten toegevoegd:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
Met scaffolding maakt u het volgende:
- Een filmscontroller:
Controllers/MoviesController.cs
-
Razor bestanden weergeven voor maken, verwijderen, details, bewerken en pagina's indexeren:
Views/Movies/*.cshtml
- Een databasecontextklasse:
Data/MvcMovieContext.cs
Scaffolding werkt het volgende bij:
- Voegt vereiste pakketverwijzingen in het
MvcMovie.csproj
projectbestand in. - Registreert de databasecontext in het
Program.cs
-bestand. - Hiermee voegt u een databaseverbindingsreeks toe aan het
appsettings.json
-bestand.
Het automatisch maken van deze bestanden en bestandsupdates wordt genoemd.
De pagina's in de scaffolded kunnen nog niet worden gebruikt omdat de database niet bestaat. Het uitvoeren van de app en het selecteren van de Film-app koppeling resulteert in een Kan de database niet openen of geen dergelijke tabel: Film foutbericht.
Bouw de app om te controleren of er geen fouten zijn.
Initiële migratie
Gebruik de functie EF CoreMigrations om de database te maken. Migrations is een set hulpprogramma's waarmee een database wordt gemaakt en bijgewerkt zodat deze overeenkomt met het gegevensmodel.
Selecteer in het menu ToolsNuGet Package Manager>Package Manager Console.
Voer in de Package Manager Console (PMC) de volgende opdrachten in:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: genereert eenMigrations/{timestamp}_InitialCreate.cs
migratiebestand. Het argumentInitialCreate
is de migratienaam. Elke naam kan worden gebruikt, maar volgens de conventie wordt een naam geselecteerd die de migratie beschrijft. Omdat dit de eerste migratie is, bevat de gegenereerde klasse code om het databaseschema te maken. Het databaseschema is gebaseerd op het model dat is opgegeven in de klasseMvcMovieContext
.Update-Database
: hiermee wordt de database bijgewerkt naar de meest recente migratie, die met de vorige opdracht is gemaakt. Met deze opdracht wordt de methodeUp
uitgevoerd in hetMigrations/{time-stamp}_InitialCreate.cs
-bestand, waarmee de database wordt gemaakt.
Met de opdracht Update-Database
wordt de volgende waarschuwing gegenereerd:
Er is geen type opgegeven voor de decimale kolom 'Prijs' op entiteitstype 'Film'. Hierdoor worden waarden ongemerkt afgekapt als ze niet in de standaard precisie en schaal passen. Geef expliciet het kolomtype SQL-server op dat geschikt is voor alle waarden met behulp van HasColumnType().
Negeer de voorgaande waarschuwing. Deze is opgelost in een latere zelfstudie.
Voor meer informatie over de PMC-hulpprogramma's voor EF Core, zie EF Core referentiemateriaal voor hulpprogramma's - PMC in Visual Studio.
De app testen
Voer de app uit en selecteer de koppeling Movie App.
Als u te maken krijgt met een uitzondering zoals hieronder aangegeven, dan hebt u mogelijk het Update-Database
-commando gemist in migratiestap .
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Notitie
Mogelijk kunt u geen decimale komma's invoeren in het veld Price
. Ter ondersteuning van jQuery-validatie voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en voor niet-US-English datumnotaties, moet de app worden geglobaliseerd. Zie dit GitHub-probleemvoor instructies voor globalisatie.
De gegenereerde databasecontextklasse en -registratie onderzoeken
Met EF Corewordt gegevenstoegang uitgevoerd met behulp van een model. Een model bestaat uit entiteitsklassen en een contextobject dat een sessie met de database vertegenwoordigt. Met het contextobject kunt u gegevens opvragen en opslaan. De databasecontext is afgeleid van Microsoft.EntityFrameworkCore.DbContext en geeft de entiteiten op die moeten worden opgenomen in het gegevensmodel.
Met scaffolding wordt de contextklasse van de Data/MvcMovieContext.cs
database gemaakt:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;
namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}
public DbSet<MvcMovie.Models.Movie> Movie { get; set; }
}
}
Met de voorgaande code maakt u een eigenschap DbSet<Movie> die de films in de database vertegenwoordigt.
Afhankelijkheidsinjectie
ASP.NET Core is gebouwd met afhankelijkheidsinjectie (DI). Services, zoals de databasecontext, worden geregistreerd bij DI in Program.cs
. Deze services worden geleverd aan onderdelen die ze nodig hebben via constructorparameters.
In het bestand Controllers/MoviesController.cs
gebruikt de constructor afhankelijkheidsinjectie om de MvcMovieContext
databasecontext in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Scaffolding heeft de volgende gemarkeerde code gegenereerd in Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
Het ASP.NET Core-configuratiesysteem leest de verbindingsreeks van de database 'MvcMovieContext'.
De gegenereerde databaseverbindingsreeks onderzoeken
Scaffolding heeft een verbindingsreeks toegevoegd aan het appsettings.json
-bestand:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Data Source=MvcMovieContext-ea7a4069-f366-4742-bd1c-3f753a804ce1.db"
}
}
Voor lokale ontwikkeling leest het ASP.NET Core-configuratiesysteem de ConnectionString
sleutel uit het appsettings.json
-bestand.
De InitialCreate
-klasse
Bekijk het Migrations/{timestamp}_InitialCreate.cs
migratiebestand:
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
In de voorgaande code:
-
InitialCreate.Up
maakt de filmtabel en configureertId
als primaire sleutel. -
InitialCreate.Down
de schemawijzigingen die door deUp
migratie zijn aangebracht, terugdraaien.
Afhankelijkheidsinjectie in de controller
Open het bestand Controllers/MoviesController.cs
en bekijk de constructor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
De constructor maakt gebruik van afhankelijkheidsinjectie om de databasecontext (MvcMovieContext
) in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Test de pagina aanmaken . Voer gegevens in en verzend deze.
Test de bewerken, detailsen pagina's verwijderen.
Sterk getypte modellen en de @model
richtlijn
Eerder in deze zelfstudie hebt u gezien hoe een controller gegevens of objecten aan een weergave kan doorgeven met behulp van de ViewData
woordenlijst. De ViewData
woordenlijst is een dynamisch object dat een handige, laat-gebonden manier biedt om informatie door te geven aan een weergave.
MVC biedt de mogelijkheid om sterk getypte modelobjecten door te geven aan een weergave. Deze sterk getypte benadering maakt controle van de code tijdens het compileren mogelijk. Het steigermechanisme heeft een sterk getypeerd model doorgegeven in de MoviesController
klasse en weergaven.
Bekijk de gegenereerde methode Details
in het bestand Controllers/MoviesController.cs
:
// 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);
}
De parameter id
wordt over het algemeen doorgegeven als routegegevens. Bijvoorbeeld https://localhost:5001/movies/details/1
sets:
- De controller naar de
movies
controller, het eerste URL-segment. - De actie voor
details
, het tweede URL-segment. - Het
id
tot 1, het laatste URL-segment.
De id
kan worden doorgegeven met een querystring, zoals in het volgende voorbeeld:
https://localhost:5001/movies/details?id=1
De parameter id
wordt gedefinieerd als een nullable type (int?
) in gevallen waarin de id
waarde niet is opgegeven.
Een lambda-expressie wordt doorgegeven aan de methode FirstOrDefaultAsync om filmentiteiten te selecteren die overeenkomen met de routegegevens of querytekenreekswaarde.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Als er een film wordt gevonden, wordt een exemplaar van het Movie
model doorgegeven aan de Details
weergave:
return View(movie);
Bekijk de inhoud van het Views/Movies/Details.cshtml
-bestand:
@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>
De @model
-instructie boven aan het weergavebestand geeft het type object op dat door de weergave wordt verwacht. Toen de filmcontroller werd gemaakt, werd de volgende @model
instructie opgenomen:
@model MvcMovie.Models.Movie
Deze @model
instructie geeft toegang tot de film die de controller heeft doorgegeven aan de weergave. Het Model
-object is sterk getypeerd. In de weergave Details.cshtml
geeft de code bijvoorbeeld elk filmveld door aan de DisplayNameFor
en DisplayFor
HTML Helpers met het sterk getypte Model
-object. De Create
en Edit
methoden en weergaven geven ook een Movie
modelobject door.
Bekijk de Index.cshtml
-weergave en de methode Index
in de controller Films. U ziet hoe de code een List
-object maakt wanneer deze de methode View
aanroept. De code geeft deze Movies
lijst door vanuit de actiemethode Index
aan de weergave:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
De code retourneert probleemdetails als de eigenschap Movie
van de gegevenscontext null is.
Toen de filmcontroller werd gemaakt, bevatte scaffolding de volgende @model
instructie boven aan het Index.cshtml
-bestand:
@model IEnumerable<MvcMovie.Models.Movie>
De @model
-instructie biedt toegang tot de lijst met films die de controller aan de weergave heeft doorgegeven met behulp van een sterk getypt Model
-object. Bijvoorbeeld, in de weergave Index.cshtml
doorloopt de code de films met een foreach
-instructie over het sterk getypeerde 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>
Omdat het Model
-object sterk is getypt als een IEnumerable<Movie>
-object, wordt elk item in de lus getypt als Movie
. De compiler valideert onder andere de typen die in de code worden gebruikt.
Aanvullende informatiebronnen
In deze handleiding worden klassen toegevoegd voor het beheren van films in een database. Deze klassen zijn het onderdeel 'Model' van de MVC-app.
Deze modelklassen worden gebruikt met Entity Framework Core (EF Core) om met een database te werken. EF Core is een ORM-framework (object-relational mapping) dat de code voor gegevenstoegang vereenvoudigt die u moet schrijven.
De gemaakte modelklassen worden POCO--klassen genoemd, afkomstig van Plain Old CLR Objects. POCO-klassen hebben geen afhankelijkheid van EF Core. Ze definiëren alleen de eigenschappen van de gegevens die moeten worden opgeslagen in de database.
In deze zelfstudie worden eerst modelklassen gemaakt en EF Core de database maakt.
Een gegevensmodelklasse toevoegen
Klik met de rechtermuisknop op de map Modellen>>Klassetoevoegen. Geef het bestand de naam Movie.cs
.
Werk het Models/Movie.cs
-bestand bij met de volgende code:
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; }
}
}
De klasse Movie
bevat een Id
veld, dat vereist is voor de database voor de primaire sleutel.
Het kenmerk DataType op ReleaseDate
geeft het type gegevens (Date
) aan. Met dit kenmerk:
- De gebruiker hoeft geen tijdgegevens in te voeren in het datumveld.
- Alleen de datum wordt weergegeven, geen tijdinformatie.
DataAnnotations worden besproken in een latere tutorial.
Het vraagteken na string
geeft aan dat de eigenschap nullable is. Zie Null-verwijzingstypenvoor meer informatie.
NuGet-pakketten toevoegen
Selecteer in het menu ToolsNuGet Package Manager>Package Manager Console (PMC).
Voer in de PMC de volgende opdracht uit:
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Met de voorgaande opdrachten voegt u het volgende toe:
- De EF Core SQL Server-provider. Het providerpakket installeert het EF Core-pakket als een afhankelijkheid.
- De hulpprogramma's die door de pakketten worden gebruikt, worden automatisch geïnstalleerd in de scaffolding-stap, verderop in de zelfstudie.
Bouw het project als controle op compilerfouten.
Basisstructuur voor filmpagina's
Gebruik de scaffolding-tool om Create
-, Read
-, Update
- en Delete
-pagina's (CRUD) te genereren voor het filmmodel.
Klik in Solution Explorermet de rechtermuisknop op de map Controllers en selecteer Toevoegen > Nieuw Scaffold-onderdeel.
Selecteer in het dialoogvenster Scaffold toevoegenMVC-controller met weergaven met behulp van Entity Framework > Toevoegen.
Voltooi het toevoegen van de MVC-controller met weergaven, door gebruik te maken van het Entity Framework dialoogvenster.
- Selecteer in de vervolgkeuzelijst ModelklasseMovie (MvcMovie.Models).
- Selecteer in de rij van de gegevenscontextklasse het + (plusteken).
- In het dialoogvenster Gegevenscontext toevoegen wordt de klassenaam MvcMovie.Data.MvcMovieContext gegenereerd.
- Selecteer toevoegen.
- weergaven en controllernaam: behoud de standaardwaarde.
- Selecteer toevoegen.
Als u een foutbericht krijgt, selecteert u een tweede keer toevoegen om het opnieuw te proberen.
De scaffolding-functie werkt het volgende bij:
- Voegt vereiste pakketverwijzingen in het
MvcMovie.csproj
projectbestand in. - Registreert de databasecontext in het
Program.cs
-bestand. - Hiermee voegt u een databaseverbindingsreeks toe aan het
appsettings.json
-bestand.
Met scaffolding maakt u het volgende:
- Een filmscontroller:
Controllers/MoviesController.cs
-
Razor bestanden weergeven voor maken, verwijderen, details, bewerken en pagina's indexeren:
Views/Movies/*.cshtml
- Een databasecontextklasse:
Data/MvcMovieContext.cs
Het automatisch aanmaken van deze bestanden en bestandsupdates wordt scaffoldinggenoemd.
De pagina's in de scaffolded kunnen nog niet worden gebruikt omdat de database niet bestaat. Het uitvoeren van de app en het selecteren van de Film-app koppeling resulteert in een Kan de database niet openen of geen dergelijke tabel: Film foutbericht.
De app bouwen
Bouw de app. De compiler genereert verschillende waarschuwingen over hoe null
waarden worden verwerkt. Zie dit GitHub-probleem en Nullable-referentietypen voor meer informatie.
Verwijder de volgende regel uit het bestand MvcMovie.csproj
om de waarschuwingen van nullable referentietypen te elimineren:
<Nullable>enable</Nullable>
We hopen dit probleem in de volgende release op te lossen.
Initiële migratie
Gebruik de functie EF CoreMigrations om de database te maken. Migrations is een set hulpprogramma's waarmee een database wordt gemaakt en bijgewerkt zodat deze overeenkomt met het gegevensmodel.
Selecteer in het menu ToolsNuGet Package Manager>Package Manager Console.
Voer in de Package Manager Console (PMC) de volgende opdrachten in:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: genereert eenMigrations/{timestamp}_InitialCreate.cs
migratiebestand. Het argumentInitialCreate
is de migratienaam. Elke naam kan worden gebruikt, maar volgens de conventie wordt een naam geselecteerd die de migratie beschrijft. Omdat dit de eerste migratie is, bevat de gegenereerde klasse code om het databaseschema te maken. Het databaseschema is gebaseerd op het model dat is opgegeven in de klasseMvcMovieContext
.Update-Database
: hiermee wordt de database bijgewerkt naar de meest recente migratie, die met de vorige opdracht is gemaakt. Met deze opdracht wordt de methodeUp
uitgevoerd in hetMigrations/{time-stamp}_InitialCreate.cs
-bestand, waarmee de database wordt gemaakt.
Met de opdracht Update-Database
wordt de volgende waarschuwing gegenereerd:
Er is geen type opgegeven voor de decimale kolom 'Prijs' op entiteitstype 'Film'. Hierdoor worden waarden onopgemerkt afgekapt als ze niet in de standaardprecisie en schaal passen. Geef expliciet het kolomtype SQL-server op dat geschikt is voor alle waarden met behulp van HasColumnType().
Negeer de voorgaande waarschuwing. Deze is opgelost in een latere zelfstudie.
Zie EF Core referentiemateriaal voor hulpprogramma's - PMC in Visual Studiovoor meer informatie over de PMC-hulpprogramma's voor EF Core.
De app testen
Voer de app uit en selecteer de koppeling Movie App.
Als u een uitzondering krijgt die vergelijkbaar is met het volgende, hebt u mogelijk de stap migraties gemist:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Notitie
Mogelijk kunt u geen decimale komma's invoeren in het veld Price
. Ter ondersteuning van jQuery-validatie voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en voor niet-US-English datumnotaties, moet de app worden geglobaliseerd. Zie dit GitHub-probleemvoor instructies voor globalisatie.
De gegenereerde databasecontextklasse en -registratie onderzoeken
Met EF Corewordt gegevenstoegang uitgevoerd met behulp van een model. Een model bestaat uit entiteitsklassen en een contextobject dat een sessie met de database vertegenwoordigt. Met het contextobject kunt u gegevens opvragen en opslaan. De databasecontext is afgeleid van Microsoft.EntityFrameworkCore.DbContext en geeft de entiteiten op die moeten worden opgenomen in het gegevensmodel.
Met scaffolding wordt de Data/MvcMovieContext.cs
-databasecontextklasse gemaakt.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using MvcMovie.Models;
namespace MvcMovie.Data
{
public class MvcMovieContext : DbContext
{
public MvcMovieContext (DbContextOptions<MvcMovieContext> options)
: base(options)
{
}
public DbSet<MvcMovie.Models.Movie> Movie { get; set; }
}
}
Met de voorgaande code maakt u een eigenschap DbSet<Movie> die de films in de database vertegenwoordigt.
Afhankelijkheidsinjectie
ASP.NET Core is gebouwd met afhankelijkheidsinjectie (DI). Services, zoals de databasecontext, worden geregistreerd bij DI in Program.cs
. Deze services worden geleverd aan onderdelen die ze nodig hebben via constructorparameters.
In het bestand Controllers/MoviesController.cs
gebruikt de constructor afhankelijkheidsinjectie om de MvcMovieContext
databasecontext in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Scaffolding heeft de volgende gemarkeerde code gegenereerd in Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
Het ASP.NET Core-configuratiesysteem leest de verbindingsreeks van de database 'MvcMovieContext'.
De gegenereerde databaseverbindingsreeks onderzoeken
Scaffolding heeft een verbindingsreeks toegevoegd aan het appsettings.json
-bestand:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-7dc5;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Voor lokale ontwikkeling leest het ASP.NET Core-configuratiesysteem de ConnectionString
sleutel uit het appsettings.json
-bestand.
De InitialCreate
-klasse
Bekijk het Migrations/{timestamp}_InitialCreate.cs
migratiebestand:
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
In de voorgaande code:
-
InitialCreate.Up
maakt de filmtabel en configureertId
als primaire sleutel. -
InitialCreate.Down
de schemawijzigingen die door deUp
migratie zijn aangebracht, terugdraaien.
Afhankelijkheidsinjectie in de controller
Open het bestand Controllers/MoviesController.cs
en bekijk de constructor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
De constructor gebruikt Dependency Injection om de databasecontext (MvcMovieContext
) in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Test de pagina maken. Voer gegevens in en verzend deze.
Test de bewerken, detailsen pagina's verwijderen.
Sterk getypte modellen en de @model
richtlijn
Eerder in deze zelfstudie hebt u gezien hoe een controller gegevens of objecten aan een weergave kan doorgeven met behulp van de ViewData
woordenlijst. De ViewData
woordenlijst is een dynamisch object dat op een handige, laat-gebonden manier een manier biedt om informatie door te geven aan een interface.
MVC biedt de mogelijkheid om sterk getypte modelobjecten door te geven aan een view. Deze sterk getype benadering stelt compile-tijdcodecontrole in staat. Het steigermechanisme heeft een sterk getypeerd model doorgegeven in de klasse MoviesController
en schermweergaves.
Bekijk de gegenereerde methode Details
in het bestand Controllers/MoviesController.cs
:
// 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);
}
De parameter id
wordt over het algemeen doorgegeven als routegegevens. Bijvoorbeeld: https://localhost:5001/movies/details/1
sets:
- De controller naar de
movies
-regelaar, het eerste URL-segment. - De actie voor
details
, het tweede URL-segment. - Het
id
tot 1, het laatste URL-segment.
Het id
kan worden doorgegeven met een queryreeks, zoals in het volgende voorbeeld:
https://localhost:5001/movies/details?id=1
De parameter id
wordt gedefinieerd als een nullable type (int?
) in gevallen waarin de id
waarde niet is opgegeven.
Een lambda-expressie wordt doorgegeven aan de methode FirstOrDefaultAsync om filmentiteiten te selecteren die overeenkomen met de routegegevens of querytekenreekswaarde.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Als er een film wordt gevonden, wordt een exemplaar van het Movie
model doorgegeven aan de Details
weergave:
return View(movie);
Bekijk de inhoud van het Views/Movies/Details.cshtml
-bestand:
@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>
De @model
-instructie boven aan het weergavebestand geeft het type object op dat door de weergave wordt verwacht. Toen de filmcontroller werd gemaakt, werd de volgende @model
instructie opgenomen:
@model MvcMovie.Models.Movie
Deze @model
-richtlijn geeft toegang tot de film die de controller aan de weergave heeft doorgegeven. Het Model
-object is sterk getypt. In de Details.cshtml
-weergave geeft de code bijvoorbeeld elk filmveld door aan de DisplayNameFor
en DisplayFor
HTML Helpers met het sterk getypte Model
-object. De Create
en Edit
methoden en weergaven geven ook een Movie
modelobject door.
Bekijk de Index.cshtml
-weergave en de methode Index
in de controller Films. U ziet hoe de code een List
-object maakt wanneer deze de methode View
aanroept. De code geeft deze Movies
lijst door vanuit de actiemethode Index
aan de weergave:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Toen de filmcontroller werd gemaakt, bevatte de scaffold-functionaliteit de volgende @model
-instructie bovenaan het Index.cshtml
-bestand.
@model IEnumerable<MvcMovie.Models.Movie>
De @model
-instructie biedt toegang tot de lijst met films die door de controller aan de weergave zijn doorgegeven, met behulp van een sterk getypeerd Model
-object. In de weergave Index.cshtml
loopt de code bijvoorbeeld door de films heen met een foreach
-instructie over het sterk getypte 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>
Omdat het Model
-object sterk is getypt als een IEnumerable<Movie>
-object, wordt elk item in de lus getypt als Movie
. De compiler valideert onder andere de typen die in de code worden gebruikt.
Aanvullende informatiebronnen
In deze handleiding worden klassen toegevoegd voor het beheren van films in een database. Deze klassen zijn het onderdeel 'Model' van de MVC-app.
Deze modelklassen worden gebruikt met Entity Framework Core (EF Core) om met een database te werken. EF Core is een ORM-framework (object-relational mapping) dat de code voor gegevenstoegang vereenvoudigt die u moet schrijven.
De gemaakte modelklassen worden POCO--klassen genoemd, van Plain Old CLR Objects. POCO-klassen hebben geen afhankelijkheid van EF Core. Ze definiëren alleen de eigenschappen van de gegevens die moeten worden opgeslagen in de database.
In deze zelfstudie worden eerst modelklassen gemaakt en EF Core de database maakt.
Een gegevensmodelklasse toevoegen
Klik met de rechtermuisknop op de map Modellen>>Klassetoevoegen. Geef het bestand de naam Movie.cs
.
Werk het Models/Movie.cs
-bestand bij met de volgende 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; }
}
}
De klasse Movie
bevat een Id
veld, dat vereist is voor de database voor de primaire sleutel.
Het kenmerk DataType op ReleaseDate
geeft het type gegevens (Date
) aan. Met dit kenmerk:
- De gebruiker hoeft geen tijdgegevens in te voeren in het datumveld.
- Alleen de datum wordt weergegeven, geen tijdinformatie.
DataAnnotations worden behandeld in een later tutorial.
NuGet-pakketten toevoegen
Selecteer in het menu ToolsNuGet Package Manager>Package Manager Console (PMC).
Voer in de PMC de volgende opdracht uit:
Install-Package Microsoft.EntityFrameworkCore.Design
Met de voorgaande opdrachten voegt u het volgende toe:
- De EF Core SQL Server-provider. Het providerpakket installeert het EF Core-pakket als een afhankelijkheid.
- De hulpprogramma's die door de pakketten worden gebruikt, worden automatisch geïnstalleerd in de scaffolding-stap, verderop in de zelfstudie.
Bouw het project als controle op compilerfouten.
Structuur van filmpagina's
Gebruik de tool om pagina's Create
, Read
, Update
en Delete
(CRUD) voor het filmmodel te maken.
Klik in Solution Explorermet de rechtermuisknop op de map Controllers en selecteer Toevoegen > Nieuw Scaffold-item.
Selecteer in het dialoogvenster Scaffold toevoegenMVC-controller met views, met behulp van Entity Framework > Toevoegen.
Voltooi de MVC-controller toevoegen met weergaven, met behulp van het dialoogvenster Entity Framework:
- Selecteer in de vervolgkeuzelijst ModelklasseMovie (MvcMovie.Models).
- Selecteer in de gegevenscontextklasse rij het + (plusteken).
- In het dialoogvenster Gegevenscontext toevoegen wordt de klassenaam MvcMovie.Data.MvcMovieContext gegenereerd.
- Selecteer toevoegen.
- weergaven en controllernaam: behoud de standaardwaarde.
- Selecteer toevoegen.
Scaffolding werkt het volgende bij:
- Voegt vereiste pakketverwijzingen in het
MvcMovie.csproj
projectbestand in. - Registreert de databasecontext in
Startup.ConfigureServices
van hetStartup.cs
-bestand. - Hiermee voegt u een databaseverbindingsreeks toe aan het
appsettings.json
-bestand.
Steigers creëren het volgende:
- Een filmscontroller:
Controllers/MoviesController.cs
-
Razor bestanden weergeven voor maken, verwijderen, details, bewerken en pagina's indexeren:
Views/Movies/*.cshtml
- Een databasecontextklasse:
Data/MvcMovieContext.cs
Het automatisch maken van deze bestanden en bestandsupdates wordt genoemd.
De pagina's in de scaffolded kunnen nog niet worden gebruikt omdat de database niet bestaat. Het uitvoeren van de app en het selecteren van de Movie App link resulteert in een Kan de database niet openen of geen dergelijke tabel: Movie foutmelding.
Initiële migratie
Gebruik de functie EF CoreMigrations om de database te maken. Migraties zijn een set hulpprogramma's waarmee een database wordt gemaakt en bijgewerkt zodat deze overeenkomt met het gegevensmodel.
Selecteer in het menu ToolsNuGet Package Manager>Package Manager Console.
Voer in de Package Manager Console (PMC) de volgende opdrachten in:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: genereert eenMigrations/{timestamp}_InitialCreate.cs
migratiebestand. Het argumentInitialCreate
is de migratienaam. Elke naam kan worden gebruikt, maar volgens de conventie wordt een naam geselecteerd die de migratie beschrijft. Omdat dit de eerste migratie is, bevat de gegenereerde klasse code om het databaseschema te maken. Het databaseschema is gebaseerd op het model dat is opgegeven in de klasseMvcMovieContext
.Update-Database
: hiermee wordt de database bijgewerkt naar de meest recente migratie, die met de vorige opdracht is gemaakt. Met deze opdracht wordt de methodeUp
uitgevoerd in hetMigrations/{time-stamp}_InitialCreate.cs
-bestand, waarmee de database wordt gemaakt.
Met de opdracht Update-Database
wordt de volgende waarschuwing gegenereerd:
Er is geen type opgegeven voor de decimale kolom 'Prijs' op entiteitstype 'Film'. Hierdoor worden waarden ongemerkt afgekapt als ze niet in de standaard nauwkeurigheid en schaal passen. Geef expliciet het kolomtype SQL-server op dat geschikt is voor alle waarden met behulp van HasColumnType().
Negeer de voorgaande waarschuwing. Deze is opgelost in een latere zelfstudie.
Voor meer informatie over de PMC-hulpprogramma's voor EF Core, zie EF Core referentiemateriaal voor hulpprogramma's - PMC in Visual Studio.
De app testen
Voer de app uit en selecteer de koppeling Movie App.
Als u een uitzondering krijgt die vergelijkbaar is met het volgende, hebt u mogelijk de stap migraties gemist:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Notitie
Mogelijk kunt u geen decimale komma's invoeren in het veld Price
. Ter ondersteuning van jQuery-validatie voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en voor niet-US-English datumnotaties, moet de app worden geglobaliseerd. Zie dit GitHub-probleemvoor instructies voor globalisatie.
De gegenereerde databasecontextklasse en -registratie onderzoeken
Met EF Corewordt gegevenstoegang uitgevoerd met behulp van een model. Een model bestaat uit entiteitsklassen en een contextobject dat een sessie met de database vertegenwoordigt. Met het contextobject kunt u gegevens opvragen en opslaan. De databasecontext is afgeleid van Microsoft.EntityFrameworkCore.DbContext en geeft de entiteiten op die moeten worden opgenomen in het gegevensmodel.
Scaffolding creëert de Data/MvcMovieContext.cs
databasecontextklasse.
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; }
}
}
Met de voorgaande code maakt u een eigenschap DbSet<Movie> die de films in de database vertegenwoordigt.
ASP.NET Core is gebouwd met afhankelijkheidsinjectie (DI). Services, zoals de databasecontext, moeten worden geregistreerd bij DI in Startup
. Onderdelen waarvoor deze services zijn vereist, worden geleverd via constructorparameters.
In het bestand Controllers/MoviesController.cs
gebruikt de constructor afhankelijkheidsinjectie om de MvcMovieContext
databasecontext in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Scaffolding heeft de volgende gemarkeerde code gegenereerd in Startup.ConfigureServices
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}
Het ASP.NET Core-configuratiesysteem leest de verbindingsreeks van de database 'MvcMovieContext'.
De gegenereerde databaseverbindingsreeks onderzoeken
Scaffolding heeft een verbindingsreeks toegevoegd aan het appsettings.json
-bestand:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Voor lokale ontwikkeling leest het ASP.NET Core-configuratiesysteem de ConnectionString
sleutel uit het appsettings.json
-bestand.
De InitialCreate
-klasse
Bekijk het Migrations/{timestamp}_InitialCreate.cs
migratiebestand:
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
In de voorgaande code:
-
InitialCreate.Up
maakt de filmtabel en configureertId
als primaire sleutel. -
InitialCreate.Down
de schemawijzigingen die door deUp
migratie zijn aangebracht, terugdraaien.
Afhankelijkheidsinjectie in de controller
Open het bestand Controllers/MoviesController.cs
en bekijk de constructor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
De constructor gebruikt afhankelijkheidsinjectie om de databasecontext (MvcMovieContext
) in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Test de pagina Maak. Voer gegevens in en verzend deze.
Test de bewerken, detailsen pagina's verwijderen.
Sterk getypte modellen en de @model
richtlijn
Eerder in deze zelfstudie hebt u gezien hoe een controller gegevens of objecten aan een weergave kan doorgeven met behulp van de ViewData
woordenlijst. De ViewData
dictionary is een dynamisch object dat een handige, laatgebonden manier biedt om informatie door te geven aan een view.
MVC biedt de mogelijkheid om sterk getypte modelobjecten door te geven aan een weergave. Deze sterk getypeerde benadering maakt het mogelijk om code tijdens compilatie te controleren. Het scaffolding-mechanisme heeft een sterk getypeerd model doorgegeven in de MoviesController
klasse en weergaves.
Bekijk de gegenereerde methode Details
in het bestand Controllers/MoviesController.cs
:
// 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);
}
De parameter id
wordt over het algemeen doorgegeven als routegegevens. Bijvoorbeeld https://localhost:5001/movies/details/1
sets:
- De controller naar de
movies
controller, het eerste URL-segment. - De actie voor
details
, het tweede URL-segment. - Het
id
tot 1, het laatste URL-segment.
De id
kan met een queryreeks worden doorgegeven, zoals in het volgende voorbeeld:
https://localhost:5001/movies/details?id=1
De parameter id
wordt gedefinieerd als een nullable type (int?
) in gevallen waarin de id
waarde niet is opgegeven.
Een lambda-expressie wordt doorgegeven aan de methode FirstOrDefaultAsync om filmentiteiten te selecteren die overeenkomen met de routegegevens of querytekenreekswaarde.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Als er een film wordt gevonden, wordt een exemplaar van het Movie
model doorgegeven aan de Details
weergave:
return View(movie);
Bekijk de inhoud van het Views/Movies/Details.cshtml
-bestand:
@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>
De @model
-instructie boven aan het weergavebestand geeft het type object op dat door de weergave wordt verwacht. Toen de filmcontroller werd gemaakt, werd de volgende @model
instructie opgenomen:
@model MvcMovie.Models.Movie
Deze @model
instructie geeft toegang tot de film die de controller heeft doorgegeven aan de weergave. Het Model
-object is sterk getypt. In de weergave Details.cshtml
geeft de code bijvoorbeeld elk filmveld door aan de DisplayNameFor
en DisplayFor
HTML Helpers met het sterk getypte Model
-object. De Create
en Edit
methoden en weergaven geven ook een Movie
modelobject door.
Bekijk de Index.cshtml
-weergave en de methode Index
in de controller Films. U ziet hoe de code een List
-object maakt wanneer deze de methode View
aanroept. De code geeft deze Movies
lijst door vanuit de actiemethode Index
aan de weergave:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Toen de filmcontroller werd gemaakt, bevatte scaffolding de volgende @model
instructie bovenaan het Index.cshtml
-bestand.
@model IEnumerable<MvcMovie.Models.Movie>
De @model
-instructie biedt toegang tot de lijst met films die de controller aan de weergave heeft doorgegeven met behulp van een Model
-object dat sterk is getypt. In de weergave Index.cshtml
wordt de code bijvoorbeeld door de films gelopen met een foreach
-instructie over het sterk getypte 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>
Omdat het Model
-object sterk is getypt als een IEnumerable<Movie>
-object, wordt elk item in de lus getypt als Movie
. De compiler valideert onder andere de typen die in de code worden gebruikt.
SQL-logboekregistratie van Entity Framework Core
Configuratie van logboeken wordt doorgaans geleverd door het gedeelte Logging
van appsettings.{Environment}.json
bestanden. Als u SQL-instructies wilt vastleggen, voegt u "Microsoft.EntityFrameworkCore.Database.Command": "Information"
toe aan het appsettings.Development.json
-bestand:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyDB-2;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
,"Microsoft.EntityFrameworkCore.Database.Command": "Information"
}
},
"AllowedHosts": "*"
}
Met de voorgaande JSON worden SQL-instructies weergegeven op de opdrachtregel en in het uitvoervenster van Visual Studio.
Voor meer informatie, zie Logging in .NET Core en ASP.NET Core en dit GitHub-probleem.
Aanvullende informatiebronnen
In deze zelfstudie worden klassen toegevoegd voor het beheren van films in een database. Deze klassen zijn het onderdeel 'Model' van de MVC-app.
Deze modelklassen worden gebruikt met Entity Framework Core (EF Core) om met een database te werken. EF Core is een ORM-framework (object-relational mapping) dat de code voor gegevenstoegang vereenvoudigt die u moet schrijven.
De gemaakte modelklassen worden POCO--klassen genoemd, van POld CLR Objects. POCO-klassen hebben geen afhankelijkheid van EF Core. Ze definiëren alleen de eigenschappen van de gegevens die moeten worden opgeslagen in de database.
In deze zelfstudie worden eerst modelklassen gemaakt en EF Core de database maakt.
Een gegevensmodelklasse toevoegen
Klik met de rechtermuisknop op de map Modellen>>Klassetoevoegen. Geef het bestand de naam Movie.cs
.
Werk het Movie.cs
-bestand bij met de volgende 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; }
}
}
De klasse Movie
bevat een Id
veld, dat vereist is voor de database voor de primaire sleutel.
Het kenmerk DataType op ReleaseDate
geeft het type gegevens (Date
) aan. Met dit kenmerk:
- De gebruiker hoeft geen tijdgegevens in te voeren in het datumveld.
- Alleen de datum wordt weergegeven, geen tijdinformatie.
DataAnnotations worden besproken in een latere handleiding.
NuGet-pakketten toevoegen
Selecteer in het menu ToolsNuGet Package Manager>Package Manager Console (PMC).
Voer in de PMC de volgende opdracht uit:
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Met de voorgaande opdracht wordt de EF Core SQL Server-provider toegevoegd. Het providerpakket installeert het EF Core-pakket als afhankelijkheid. Extra pakketten worden later in de zelfstudie tijdens de scaffolding-stap automatisch geïnstalleerd.
Een databasecontextklasse maken
Er is een databasecontextklasse nodig om EF Core functionaliteit (maken, lezen, bijwerken, verwijderen) voor het Movie
model te coördineren. De databasecontext is afgeleid van Microsoft.EntityFrameworkCore.DbContext en geeft de entiteiten op die moeten worden opgenomen in het gegevensmodel.
Maak een map Data.
Voeg een Data/MvcMovieContext.cs
-bestand toe met de volgende 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; }
}
}
Met de voorgaande code maakt u voor de entiteitsset een eigenschap DbSet<Movie> aan. In Entity Framework-terminologie komt een entiteitsset meestal overeen met een databasetabel. Een entiteit komt overeen met een rij in de tabel.
De databasecontext registreren
ASP.NET Core is gebouwd met afhankelijkheidsinjectie (DI). Services (zoals de EF Core DB-context) moeten worden geregistreerd bij DI tijdens het opstarten van de toepassing. Onderdelen waarvoor deze services (zoals Razor Pagina's) zijn vereist, worden aangeboden via parameters van de constructor. De constructorcode die een DB-contextinstantie ophaalt, wordt later in de handleiding weergegeven. In deze sectie registreert u de databasecontext bij de DI-container.
Voeg de volgende using
verklaringen bovenaan Startup.cs
toe:
using MvcMovie.Data;
using Microsoft.EntityFrameworkCore;
Voeg de volgende gemarkeerde code toe in Startup.ConfigureServices
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}
De naam van de verbindingsreeks wordt doorgegeven aan de context door een methode aan te roepen voor een DbContextOptions-object. Voor lokale ontwikkeling leest het ASP.NET Core-configuratiesysteem de verbindingsreeks uit het appsettings.json
-bestand leest.
De databaseverbindingsreeks onderzoeken
Voeg een verbindingsreeks toe aan het appsettings.json
-bestand:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Bouw het project als controle op compilerfouten.
Filmpagina's van scaffold
Gebruik het scaffolding-hulpprogramma om pagina's voor maken, lezen, bijwerken en verwijderen (CRUD) te genereren voor het filmmodel.
Klik in Solution Explorermet de rechtermuisknop op de map Controllers> Add > New Scaffolded Item.
Selecteer in het dialoogvenster Scaffold toevoegenMVC-controller met weergaven met behulp van Entity Framework > Toevoegen.
Voltooi het dialoogvenster Controller toevoegen:
- Modelklasse:Movie (MvcMovie.Models)
- Gegevenscontextklasse:MvcMovieContext (MvcMovie.Data)
- weergaven: De standaardinstelling van elke optie ingeschakeld houden
- Controllernaam: De standaardnaam MoviesController behouden
- Selecteer toevoegen
Visual Studio maakt:
- Een filmscontroller (
Controllers/MoviesController.cs
) - Razor bestanden bekijken voor pagina's Maken, Verwijderen, Details, Bewerken en Index (*Bekijken/Films/`.cshtml`)
Het automatisch maken van deze bestanden wordt genoemd.
U kunt de voorgedefinieerde pagina's nog niet gebruiken omdat de database niet bestaat. Als u de app uitvoert en op de koppeling Film-app klikt, krijgt u een Kan database niet openen of geen dergelijke tabel: Film foutmelding.
Initiële migratie
Gebruik de functie EF CoreMigrations om de database te maken. Migraties is een set hulpprogramma's waarmee u een database kunt maken en bijwerken zodat deze overeenkomt met uw gegevensmodel.
Selecteer in het menu ToolsNuGet Package Manager>Package Manager Console (PMC).
Voer in de PMC de volgende opdrachten in:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: genereert eenMigrations/{timestamp}_InitialCreate.cs
migratiebestand. Het argumentInitialCreate
is de migratienaam. Elke naam kan worden gebruikt, maar volgens de conventie wordt een naam geselecteerd die de migratie beschrijft. Omdat dit de eerste migratie is, bevat de gegenereerde klasse code om het databaseschema te maken. Het databaseschema is gebaseerd op het model dat is opgegeven in de klasseMvcMovieContext
.Update-Database
: hiermee wordt de database bijgewerkt naar de meest recente migratie, die met de vorige opdracht is gemaakt. Met deze opdracht wordt de methodeUp
uitgevoerd in hetMigrations/{time-stamp}_InitialCreate.cs
-bestand, waarmee de database wordt gemaakt.Met de opdracht voor het bijwerken van de database wordt de volgende waarschuwing gegenereerd:
Er is geen type opgegeven voor de decimale kolom 'Prijs' op entiteitstype 'Film'. Hierdoor worden waarden stilletjes afgekapt als ze niet in de standaardprecisie en schaal passen. Geef expliciet het kolomtype SQL-server op dat geschikt is voor alle waarden met behulp van HasColumnType().
Je kunt die waarschuwing negeren, het wordt in een latere handleiding opgelost.
Voor meer informatie over de PMC-hulpprogramma's voor EF Core, zie het referentiemateriaal voor EF Core-hulpprogramma's - PMC in Visual Studio.
De klasse InitialCreate
Bekijk het Migrations/{timestamp}_InitialCreate.cs
migratiebestand:
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");
}
}
De methode Up
maakt de tabel Movie en configureert Id
als primaire sleutel. Met de methode Down
worden de schemawijzigingen die door de Up
migratie zijn aangebracht, teruggezet.
De app testen
Voer de app uit en klik op de koppeling Movie App.
Als u een uitzondering krijgt die vergelijkbaar is met een van de volgende:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Waarschijnlijk hebt u de migratiestapgemist.
Test de pagina maken. Voer gegevens in en verzend deze.
Notitie
Mogelijk kunt u geen decimale komma's invoeren in het veld
Price
. Ter ondersteuning van jQuery-validatie voor niet-Engelse landinstellingen die een komma (",") gebruiken voor een decimaalteken en voor niet-US-English datumnotaties, moet de app worden geglobaliseerd. Zie dit GitHub-probleemvoor instructies voor globalisatie.Test de bewerken, detailsen pagina's verwijderen.
Afhankelijkheidsinjectie in de controller
Open het bestand Controllers/MoviesController.cs
en bekijk de constructor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
De constructor gebruikt afhankelijkheidsinjectie om de databasecontext (MvcMovieContext
) in de controller te injecteren. De databasecontext wordt gebruikt in elk van de CRUD methoden in de controller.
Sterk getypte modellen en het trefwoord @model
Eerder in deze zelfstudie hebt u gezien hoe een controller gegevens of objecten aan een weergave kan doorgeven met behulp van de ViewData
woordenlijst. De ViewData
dictionary is een dynamisch object dat een handige, laat-gebonden manier biedt om informatie door te geven aan een view.
MVC biedt ook de mogelijkheid om sterk getype modelobjecten door te geven aan een weergave. Deze sterk getypte benadering maakt controle van de code tijdens het compileren mogelijk. Het mechanisme voor de scaffolding heeft deze benadering (dat wil zeggen, een sterk getypt model doorgeven) toegepast op de MoviesController
klasse en view.
Bekijk de gegenereerde methode Details
in het bestand Controllers/MoviesController.cs
:
// 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);
}
De parameter id
wordt over het algemeen doorgegeven als routegegevens. Bijvoorbeeld https://localhost:5001/movies/details/1
sets:
- De controller van de
movies
controller (het eerste URL-segment). - De actie voor
details
(het tweede URL-segment). - Stel de id in op 1 (het laatste URL-segment).
U kunt de id
ook als volgt doorgeven met een querytekenreeks:
https://localhost:5001/movies/details?id=1
De parameter id
is gedefinieerd als een nullable type (int?
) als er geen id-waarde is opgegeven.
Een lambda-expressie wordt doorgegeven aan FirstOrDefaultAsync
om filmentiteiten te selecteren die overeenkomen met de routegegevens of querytekenreekswaarde.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Als er een film wordt gevonden, wordt een exemplaar van het Movie
model doorgegeven aan de Details
weergave:
return View(movie);
Bekijk de inhoud van het Views/Movies/Details.cshtml
-bestand:
@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>
De @model
-instructie boven aan het weergavebestand geeft het type object op dat door de weergave wordt verwacht. Toen de filmcontroller werd gemaakt, werd de volgende @model
instructie opgenomen:
@model MvcMovie.Models.Movie
Deze @model
richtlijn geeft toegang tot de film die de controller aan de weergave heeft overgedragen. Het Model
-object is sterk getypt. Bijvoorbeeld, in de Details.cshtml
-weergave geeft de code elk filmveld door aan de DisplayNameFor
en DisplayFor
HTML-helpers met het sterk getypte Model
-object. De Create
en Edit
methoden en weergaven geven ook een Movie
modelobject door.
Bekijk de Index.cshtml
-weergave en de methode Index
in de controller Films. U ziet hoe de code een List
-object maakt wanneer deze de methode View
aanroept. De code geeft deze Movies
lijst door vanuit de actiemethode Index
aan de weergave:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Toen de filmcontroller werd gemaakt, bevatte het sjabloon de volgende @model
instructie bovenaan het Index.cshtml
-bestand:
@model IEnumerable<MvcMovie.Models.Movie>
Met de @model
instructie kunt u toegang krijgen tot de lijst met films die de controller heeft doorgegeven aan de weergave met behulp van een Model
-object dat sterk is getypt. In de Index.cshtml
-weergave loopt de code bijvoorbeeld door de films met een foreach
-instructie over het sterk getypte 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>
Omdat het Model
-object sterk getypeerd is (als een IEnumerable<Movie>
-object), is elk item in de lus getypeerd als Movie
. Dit betekent onder andere dat u controle van de code tijdens de compilatietijd krijgt.