Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Warning
Den här versionen av ASP.NET Core stöds inte längre. Mer information finns i supportpolicyn för .NET och .NET Core. För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
Important
Den här informationen gäller en förhandsversionsprodukt som kan ändras avsevärt innan den släpps kommersiellt. Microsoft lämnar inga garantier, uttryckliga eller underförstådda, med avseende på den information som tillhandahålls här.
För den nuvarande utgåvan, se .NET 9-versionen av den här artikeln .
Av Rick Anderson och Jon P Smith.
I den här självstudien har klasser lagts till för att hantera filmer i en databas. Dessa klasser är "Model"-delen av MVC-appen.
Dessa modellklasser används med Entity Framework Core (EF Core) för att arbeta med en databas. EF Core är ett ramverk för objektrelationsmappning (ORM) som förenklar den dataåtkomstkod som du måste skriva.
De modellklasser som skapas kallas POCO-klasser , från Plain Old CLR Objects. POCO-klasser har inget beroende av EF Core. De definierar bara egenskaperna för de data som ska lagras i databasen.
I den här självstudien skapas modellklasser först och EF Core skapar databasen.
Lägga till en datamodellklass
Högerklicka på mappen >Lägg till>klass. Ge filen namnet Movie.cs.
Uppdatera filen Models/Movie.cs med följande kod:
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; }
}
Klassen Movie innehåller ett Id fält som krävs av databasen för den primära nyckeln.
Attributet DataType på ReleaseDate anger typen av data (Date). Med det här attributet:
- Användaren behöver inte ange tidsinformation i datumfältet.
- Endast datumet visas, inte tidsinformation.
DataAnnotations behandlas i en senare handledning.
Frågetecknet efter string anger att egenskapen är null. För mer information, se nullbara referenstyper.
Lägga till NuGet-paket
Visual Studio installerar automatiskt de paket som krävs.
Skapa projektet som en kontroll av kompilatorfel.
Strukturera filmsidor
Använd verktyget scaffolding för att skapa Create, Read, Updateoch Delete (CRUD) sidor för filmmodellen.
Högerklicka på mappen Controllers i Solution Explorer och välj Lägg till > nytt autogenererat objekt.
               
              
            
I dialogrutan Lägg till nytt scaffoldat objekt
- I den vänstra rutan väljer du Installerad>gemensam>MVC.
- Välj MVC-styrenhet med vyer med Entity Framework.
- Välj Lägg till.
               
              
            
Slutför dialogrutan Lägg till MVC-styrenhet med vyer med hjälp av entitetsramverket :
- I listrutan Modellklass väljer du Film (MvcMovie.Models).
- I raden Datakontextklass väljer du tecknet + (plus).
- I dialogrutan Lägg till datakontext genereras klassnamnet MvcMovie.Data.MvcMovieContext .
- Välj Lägg till.
 
- I listrutan Databasprovider väljer du SQL Server.
- Vyer och kontrollantnamn: Behåll standardvärdet.
- Välj Lägg till.
               
              
            
Om du får ett felmeddelande väljer du Lägg till en andra gång för att försöka igen.
Scaffolding lägger till följande paket:
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Tools
- Microsoft.VisualStudio.Web.CodeGeneration.Design
Scaffolding skapar följande:
- En filmkontroller: Controllers/MoviesController.cs
- 
              Razor visa filer för sidorna Skapa, Ta bort, Information, Redigera och Index : Views/Movies/*.cshtml
- En databaskontextklass: Data/MvcMovieContext.cs
Scaffolding uppdaterar följande:
- Infogar nödvändiga paketreferenser i MvcMovie.csprojprojektfilen.
- Registrerar databaskontexten Program.csi filen.
- Lägger till en databasanslutningssträng i appsettings.jsonfilen.
Automatisk skapande av dessa filer och filuppdateringar kallas scaffolding.
Det går inte att använda de autogenererade sidorna ännu eftersom databasen inte finns. Om du kör appen och väljer länken Filmapp visas ett Felmeddelande om att det inte går att öppna databasen eller att det inte finns någon sådan tabell: Felmeddelande om film .
Skapa appen för att kontrollera att det inte finns några fel.
Inledande migrering
EF Core Använd migreringsfunktionen för att skapa databasen. Migreringar är en uppsättning verktyg som skapar och uppdaterar en databas som matchar datamodellen.
På menyn Verktyg väljer du NuGet Package Manager>Konsol.
I Package Manager Console (PMC) anger du följande kommando:
Add-Migration InitialCreate
- 
              Add-Migration InitialCreate: Skapar enMigrations/{timestamp}_InitialCreate.csmigreringsfil. ArgumentetInitialCreateär migreringsnamnet. Valfritt namn kan användas, men enligt konventionen väljs ett namn som beskriver migreringen. Eftersom det här är den första migreringen innehåller den genererade klassen kod för att skapa databasschemat. Databasschemat baseras på den modell som anges iMvcMovieContextklassen.
Följande varning visas, som åtgärdas i ett senare steg:
Ingen butikstyp angavs för decimalegenskapen "Price" för entitetstypen "Film". Detta gör att värdena beskärs automatiskt om de inte får plats i standardprecisionen och skalan. Ange uttryckligen den SQL-serverkolumntyp som kan hantera alla värden i OnModelCreating med hjälp av "HasColumnType", ange precision och skalning med hjälp av "HasPrecision" eller konfigurera en värdekonverterare med hjälp av "HasConversion".
I PMC anger du följande kommando:
Update-Database
- 
              Update-Database: Uppdaterar databasen till den senaste migreringen, som föregående kommando skapade. Det här kommandot körUp-metoden iMigrations/{time-stamp}_InitialCreate.csfilen, som skapar databasen.
Mer information om PMC-verktygen för EF Corefinns i verktygsreferensEF Core – PMC i Visual Studio.
Testa appen
Kör appen och välj länken Filmapp .
Om du får ett undantag som liknar följande kan du ha missat Update-Database kommandot i migreringssteget:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Note
Du kanske inte kan ange decimaltecken i fältet Price. För att stödja jQuery-validering för språk som inte är engelska och som använder kommatecken (",") för en decimalpunkt och för datumformat som inte är US-English måste appen globaliseras. Globaliseringsinstruktioner finns i det här GitHub-problemet.
Granska den genererade databaskontextklassen och registreringen
Med EF Coreutförs dataåtkomst med hjälp av en modell. En modell består av entitetsklasser och ett kontextobjekt som representerar en session med databasen. Med kontextobjektet kan du köra frågor mot och spara data. Databaskontexten härleds från Microsoft.EntityFrameworkCore.DbContext och anger de entiteter som ska ingå i datamodellen.
Byggnadsställningar skapar databaskontextklassen Data/MvcMovieContext.cs :
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!;
    }
}
Föregående kod skapar en DbSet<Movie-egenskap> som representerar filmerna i databasen.
Beroendeinsprutning
ASP.NET Core skapas med beroendeinmatning (DI). Tjänster, till exempel databaskontexten, registreras med DI i Program.cs. Dessa tjänster tillhandahålls till komponenter som kräver dem via konstruktorparametrar.
              Controllers/MoviesController.cs I filen använder konstruktorn Dependency Injection för att injicera databaskontexten MvcMovieContext i kontrollern. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Scaffolding genererade följande markerade kod i 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.")));
Konfigurationssystemet ASP.NET Core läser databasanslutningssträngen "MvcMovieContext".
Granska den genererade databasanslutningssträngen
Scaffolding lade till en anslutningssträng i appsettings.json filen:
{
  "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"
  }
}
För lokal utveckling läser konfigurationssystemet ASP.NET Core nyckeln från ConnectionString-filen.
Klassen InitialCreate
Granska migreringsfilen Migrations/{timestamp}_InitialCreate.cs :
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");
        }
    }
}
I koden ovan:
- 
              InitialCreate.Upskapar tabellen Film och konfigurerarIdsom primär nyckel.
- 
              InitialCreate.Downåterställer schemaändringarna som gjorts av migreringenUp.
Beroendeinmatning i kontrollanten
              Controllers/MoviesController.cs Öppna filen och granska konstruktorn:
public class MoviesController : Controller
{
    private readonly MvcMovieContext _context;
    public MoviesController(MvcMovieContext context)
    {
        _context = context;
    }
Konstruktorn använder beroendeinmatning för att mata in databaskontexten (MvcMovieContext) i kontrollanten. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Testa Skapa-sidan. Ange och skicka data.
Testa sidorna Redigera, Information och Ta bort .
Starkt skrivna modeller och @model direktivet
Tidigare i den här självstudien såg du hur en kontrollant kan skicka data eller objekt till en vy med hjälp av ViewData ordlistan. Ordlistan ViewData är ett dynamiskt objekt som ger ett bekvämt sent bundet sätt att skicka information till en vy.
MVC ger möjlighet att skicka starkt typerade modellobjekt till en vy. Med det här starkt typade tillvägagångssättet möjliggörs kompileringskontroll. Scaffolding-mekanismen överförde en starkt typad modell i klassen och vyerna i MoviesController.
Granska den genererade Details metoden i Controllers/MoviesController.cs filen:
// 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);
}
Parametern id skickas vanligtvis som routningsdata. Till exempel https://localhost:{PORT}/movies/details/1 sätter:
- Kontrollern till kontrollern movies, det första URL-segmentet.
- Åtgärden för details, den andra URL-segmentet.
- Från idtill 1, det sista URL-segmentet.
              id Kan skickas med en frågesträng, som i följande exempel:
https://localhost:{PORT}/movies/details?id=1
Parametern id definieras som en nullbar typ (int?) i de fall då id värdet inte anges.
Ett lambda-uttryck skickas till FirstOrDefaultAsync metoden för att välja filmentiteter som matchar routningsdata eller frågesträngsvärdet.
var movie = await _context.Movie
    .FirstOrDefaultAsync(m => m.Id == id);
Om en film hittas skickas en instans av Movie modellen till Details vyn:
return View(movie);
Granska innehållet i Views/Movies/Details.cshtml filen:
@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>
Instruktionen @model överst i vyfilen anger vilken typ av objekt som vyn förväntar sig. När filmkontrollanten skapades inkluderades följande @model instruktion:
@model MvcMovie.Models.Movie
Det här @model direktivet ger åtkomst till filmen som kontrollanten skickade till vyn. Objektet Model är starkt typat. I Details.cshtml-vyn skickar koden varje filmfält till DisplayNameFor och DisplayFor HTML-hjälpare med det starkt typerade Model-objektet. Metoderna Create och Edit vyerna skickar också ett Movie modellobjekt.
Granska Index.cshtml vyn och Index metoden i filmmodulens kontroll. Observera hur koden skapar ett List objekt när den anropar View metoden. Koden skickar den här Movies listan från Index åtgärdsmetoden till vyn:
// GET: Movies
public async Task<IActionResult> Index()
{
    return View(await _context.Movie.ToListAsync());
}
Koden returnerar probleminformation om Movie egenskapen för datakontexten är null.
När filmkontrollern skapades innehöll scaffold följande @model sats överst i Index.cshtml filen.
@model IEnumerable<MvcMovie.Models.Movie>
Direktivet @model ger åtkomst till listan över filmer som kontrollanten skickade till vyn med hjälp av ett Model objekt som är starkt skrivet. I vyn loopar koden till exempel Index.cshtml igenom filmerna med en foreach instruktion över det starkt typerade Model objektet:
@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>
Eftersom objektet Model är starkt skrivet som ett IEnumerable<Movie> objekt, skrivs varje objekt i loopen som Movie. Kompilatorn validerar bland annat de typer som används i koden.
Ytterligare resurser
I den här självstudien har klasser lagts till för att hantera filmer i en databas. Dessa klasser är "Model"-delen av MVC-appen.
Dessa modellklasser används med Entity Framework Core (EF Core) för att arbeta med en databas. EF Core är ett ramverk för objektrelationsmappning (ORM) som förenklar den dataåtkomstkod som du måste skriva.
De modellklasser som skapas kallas POCO-klasser , från Plain Old CLR Objects. POCO-klasser har inget beroende av EF Core. De definierar bara egenskaperna för de data som ska lagras i databasen.
I den här självstudien skapas modellklasser först och EF Core skapar databasen.
Lägga till en datamodellklass
Högerklicka på mappen >Lägg till>klass. Ge filen namnet Movie.cs.
Uppdatera filen Models/Movie.cs med följande kod:
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; }
}
Klassen Movie innehåller ett Id fält som krävs av databasen för den primära nyckeln.
Attributet DataType på ReleaseDate anger typen av data (Date). Med det här attributet:
- Användaren behöver inte ange tidsinformation i datumfältet.
- Endast datumet visas, inte tidsinformation.
DataAnnotations behandlas i en senare handledning.
Frågetecknet efter string anger att egenskapen är null. För mer information, se nullbara referenstyper.
Lägga till NuGet-paket
Visual Studio installerar automatiskt de paket som krävs.
Skapa projektet som en kontroll av kompilatorfel.
Strukturera filmsidor
Använd verktyget scaffolding för att skapa Create, Read, Updateoch Delete (CRUD) sidor för filmmodellen.
Högerklicka på mappen Controllers i Solution Explorer och välj Lägg till > nytt autogenererat objekt.
               
              
            
I dialogrutan Lägg till nytt scaffoldat objekt
- I den vänstra rutan väljer du Installerad>gemensam>MVC.
- Välj MVC-styrenhet med vyer med Entity Framework.
- Välj Lägg till.
               
              
            
Slutför dialogrutan Lägg till MVC-styrenhet med vyer med hjälp av entitetsramverket :
- I listrutan Modellklass väljer du Film (MvcMovie.Models).
- I raden Datakontextklass väljer du tecknet + (plus).
- I dialogrutan Lägg till datakontext genereras klassnamnet MvcMovie.Data.MvcMovieContext .
- Välj Lägg till.
 
- I listrutan Databasprovider väljer du SQL Server.
- Vyer och kontrollantnamn: Behåll standardvärdet.
- Välj Lägg till.
               
              
            
Om du får ett felmeddelande väljer du Lägg till en andra gång för att försöka igen.
Scaffolding lägger till följande paket:
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Tools
- Microsoft.VisualStudio.Web.CodeGeneration.Design
Scaffolding skapar följande:
- En filmkontroller: Controllers/MoviesController.cs
- 
              Razor visa filer för sidorna Skapa, Ta bort, Information, Redigera och Index : Views/Movies/*.cshtml
- En databaskontextklass: Data/MvcMovieContext.cs
Scaffolding uppdaterar följande:
- Infogar nödvändiga paketreferenser i MvcMovie.csprojprojektfilen.
- Registrerar databaskontexten Program.csi filen.
- Lägger till en databasanslutningssträng i appsettings.jsonfilen.
Automatisk skapande av dessa filer och filuppdateringar kallas scaffolding.
Det går inte att använda de autogenererade sidorna ännu eftersom databasen inte finns. Om du kör appen och väljer länken Filmapp visas ett Felmeddelande om att det inte går att öppna databasen eller att det inte finns någon sådan tabell: Felmeddelande om film .
Skapa appen för att kontrollera att det inte finns några fel.
Inledande migrering
EF Core Använd migreringsfunktionen för att skapa databasen. Migreringar är en uppsättning verktyg som skapar och uppdaterar en databas som matchar datamodellen.
På menyn Verktyg väljer du NuGet Package Manager>Konsol.
I Package Manager Console (PMC) anger du följande kommandon:
Add-Migration InitialCreate
Update-Database
- Add-Migration InitialCreate: Skapar en- Migrations/{timestamp}_InitialCreate.csmigreringsfil. Argumentet- InitialCreateär migreringsnamnet. Valfritt namn kan användas, men enligt konventionen väljs ett namn som beskriver migreringen. Eftersom det här är den första migreringen innehåller den genererade klassen kod för att skapa databasschemat. Databasschemat baseras på den modell som anges i- MvcMovieContextklassen.
- Update-Database: Uppdaterar databasen till den senaste migreringen, som föregående kommando skapade. Det här kommandot kör- Up-metoden i- Migrations/{time-stamp}_InitialCreate.csfilen, som skapar databasen.
Kommandot Update-Database genererar följande varning:
Ingen butikstyp angavs för decimalegenskapen "Price" för entitetstypen "Film". Detta gör att värdena beskärs automatiskt om de inte får plats i standardprecisionen och skalan. Ange uttryckligen den SQL-serverkolumntyp som kan hantera alla värden i OnModelCreating med hjälp av "HasColumnType", ange precision och skalning med hjälp av "HasPrecision" eller konfigurera en värdekonverterare med hjälp av "HasConversion".
Ignorera föregående varning, den åtgärdas i en senare handledning.
Mer information om PMC-verktygen för EF Corefinns i verktygsreferensEF Core – PMC i Visual Studio.
Testa appen
Kör appen och välj länken Filmapp .
Om du får ett undantag som liknar följande kan du ha missat Update-Database kommandot i migreringssteget:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Note
Du kanske inte kan ange decimaltecken i fältet Price. För att stödja jQuery-validering för språk som inte är engelska och som använder kommatecken (",") för en decimalpunkt och för datumformat som inte är US-English måste appen globaliseras. Globaliseringsinstruktioner finns i det här GitHub-problemet.
Granska den genererade databaskontextklassen och registreringen
Med EF Coreutförs dataåtkomst med hjälp av en modell. En modell består av entitetsklasser och ett kontextobjekt som representerar en session med databasen. Med kontextobjektet kan du köra frågor mot och spara data. Databaskontexten härleds från Microsoft.EntityFrameworkCore.DbContext och anger de entiteter som ska ingå i datamodellen.
Byggnadsställningar skapar databaskontextklassen Data/MvcMovieContext.cs :
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; }
    }
}
Föregående kod skapar en DbSet<Movie-egenskap> som representerar filmerna i databasen.
Beroendeinsprutning
ASP.NET Core skapas med beroendeinmatning (DI). Tjänster, till exempel databaskontexten, registreras med DI i Program.cs. Dessa tjänster tillhandahålls till komponenter som kräver dem via konstruktorparametrar.
              Controllers/MoviesController.cs I filen använder konstruktorn Dependency Injection för att injicera databaskontexten MvcMovieContext i kontrollern. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Scaffolding genererade följande markerade kod i Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
Konfigurationssystemet ASP.NET Core läser databasanslutningssträngen "MvcMovieContext".
Granska den genererade databasanslutningssträngen
Scaffolding lade till en anslutningssträng i appsettings.json filen:
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MvcMovieContext": "Data Source=MvcMovieContext-ea7a4069-f366-4742-bd1c-3f753a804ce1.db"
  }
}
För lokal utveckling läser konfigurationssystemet ASP.NET Core nyckeln från ConnectionString-filen.
Klassen InitialCreate
Granska migreringsfilen Migrations/{timestamp}_InitialCreate.cs :
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");
        }
    }
}
I koden ovan:
- 
              InitialCreate.Upskapar tabellen Film och konfigurerarIdsom primär nyckel.
- 
              InitialCreate.Downåterställer schemaändringarna som gjorts av migreringenUp.
Beroendeinmatning i kontrollanten
              Controllers/MoviesController.cs Öppna filen och granska konstruktorn:
public class MoviesController : Controller
{
    private readonly MvcMovieContext _context;
    public MoviesController(MvcMovieContext context)
    {
        _context = context;
    }
Konstruktorn använder beroendeinmatning för att mata in databaskontexten (MvcMovieContext) i kontrollanten. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Testa Skapa-sidan. Ange och skicka data.
Testa sidorna Redigera, Information och Ta bort .
Starkt skrivna modeller och @model direktivet
Tidigare i den här självstudien såg du hur en kontrollant kan skicka data eller objekt till en vy med hjälp av ViewData ordlistan. Ordlistan ViewData är ett dynamiskt objekt som ger ett bekvämt sent bundet sätt att skicka information till en vy.
MVC ger möjlighet att skicka starkt typerade modellobjekt till en vy. Med det här starkt typade tillvägagångssättet möjliggörs kompileringskontroll. Scaffolding-mekanismen överförde en starkt typad modell i klassen och vyerna i MoviesController.
Granska den genererade Details metoden i Controllers/MoviesController.cs filen:
// 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);
}
Parametern id skickas vanligtvis som routningsdata. Till exempel https://localhost:5001/movies/details/1 sätter:
- Kontrollern till kontrollern movies, det första URL-segmentet.
- Åtgärden för details, den andra URL-segmentet.
- Från idtill 1, det sista URL-segmentet.
              id Kan skickas med en frågesträng, som i följande exempel:
https://localhost:5001/movies/details?id=1
Parametern id definieras som en nullbar typ (int?) i de fall då id värdet inte anges.
Ett lambda-uttryck skickas till FirstOrDefaultAsync metoden för att välja filmentiteter som matchar routningsdata eller frågesträngsvärdet.
var movie = await _context.Movie
    .FirstOrDefaultAsync(m => m.Id == id);
Om en film hittas skickas en instans av Movie modellen till Details vyn:
return View(movie);
Granska innehållet i Views/Movies/Details.cshtml filen:
@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>
Instruktionen @model överst i vyfilen anger vilken typ av objekt som vyn förväntar sig. När filmkontrollanten skapades inkluderades följande @model instruktion:
@model MvcMovie.Models.Movie
Det här @model direktivet ger åtkomst till filmen som kontrollanten skickade till vyn. Objektet Model är starkt typat. I Details.cshtml-vyn skickar koden varje filmfält till DisplayNameFor och DisplayFor HTML-hjälpare med det starkt typerade Model-objektet. Metoderna Create och Edit vyerna skickar också ett Movie modellobjekt.
Granska Index.cshtml vyn och Index metoden i filmmodulens kontroll. Observera hur koden skapar ett List objekt när den anropar View metoden. Koden skickar den här Movies listan från Index åtgärdsmetoden till vyn:
// GET: Movies
public async Task<IActionResult> Index()
{
    return View(await _context.Movie.ToListAsync());
}
Koden returnerar probleminformation om Movie egenskapen för datakontexten är null.
När filmkontrollern skapades innehöll scaffold följande @model sats överst i Index.cshtml filen.
@model IEnumerable<MvcMovie.Models.Movie>
Direktivet @model ger åtkomst till listan över filmer som kontrollanten skickade till vyn med hjälp av ett Model objekt som är starkt skrivet. I vyn loopar koden till exempel Index.cshtml igenom filmerna med en foreach instruktion över det starkt typerade Model objektet:
@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>
Eftersom objektet Model är starkt skrivet som ett IEnumerable<Movie> objekt, skrivs varje objekt i loopen som Movie. Kompilatorn validerar bland annat de typer som används i koden.
Ytterligare resurser
I den här självstudien har klasser lagts till för att hantera filmer i en databas. Dessa klasser är "Model"-delen av MVC-appen.
Dessa modellklasser används med Entity Framework Core (EF Core) för att arbeta med en databas. EF Core är ett ramverk för objektrelationsmappning (ORM) som förenklar den dataåtkomstkod som du måste skriva.
De modellklasser som skapas kallas POCO-klasser , från Plain Old CLR Objects. POCO-klasser har inget beroende av EF Core. De definierar bara egenskaperna för de data som ska lagras i databasen.
I den här självstudien skapas modellklasser först och EF Core skapar databasen.
Lägga till en datamodellklass
Högerklicka på mappen >Lägg till>klass. Ge filen namnet Movie.cs.
Uppdatera filen Models/Movie.cs med följande kod:
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; }
}
Klassen Movie innehåller ett Id fält som krävs av databasen för den primära nyckeln.
Attributet DataType på ReleaseDate anger typen av data (Date). Med det här attributet:
- Användaren behöver inte ange tidsinformation i datumfältet.
- Endast datumet visas, inte tidsinformation.
DataAnnotations behandlas i en senare handledning.
Frågetecknet efter string anger att egenskapen är null. För mer information, se nullbara referenstyper.
Lägga till NuGet-paket
Visual Studio installerar automatiskt de paket som krävs.
Skapa projektet som en kontroll av kompilatorfel.
Strukturera filmsidor
Använd verktyget scaffolding för att skapa Create, Read, Updateoch Delete (CRUD) sidor för filmmodellen.
Högerklicka på mappen Controllers i Solution Explorer och välj Lägg till > nytt autogenererat objekt.
               
              
            
I dialogrutan Lägg till nytt scaffoldat objekt
- I den vänstra rutan väljer du Installerad>gemensam>MVC.
- Välj MVC-styrenhet med vyer med Entity Framework.
- Välj Lägg till.
               
              
            
Slutför dialogrutan Lägg till MVC-styrenhet med vyer med hjälp av entitetsramverket :
- I listrutan Modellklass väljer du Film (MvcMovie.Models).
- I raden Datakontextklass väljer du tecknet + (plus).
- I dialogrutan Lägg till datakontext genereras klassnamnet MvcMovie.Data.MvcMovieContext .
- Välj Lägg till.
 
- I listrutan Databasprovider väljer du SQL Server.
- Vyer och kontrollantnamn: Behåll standardvärdet.
- Välj Lägg till.
               Om du får ett felmeddelande väljer du Lägg till en andra gång för att försöka igen.
               Om du får ett felmeddelande väljer du Lägg till en andra gång för att försöka igen.
Scaffolding lägger till följande paket:
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Tools
- Microsoft.VisualStudio.Web.CodeGeneration.Design
Scaffolding skapar följande:
- En filmkontroller: Controllers/MoviesController.cs
- 
              Razor visa filer för sidorna Skapa, Ta bort, Information, Redigera och Index : Views/Movies/*.cshtml
- En databaskontextklass: Data/MvcMovieContext.cs
Scaffolding uppdaterar följande:
- Infogar nödvändiga paketreferenser i MvcMovie.csprojprojektfilen.
- Registrerar databaskontexten Program.csi filen.
- Lägger till en databasanslutningssträng i appsettings.jsonfilen.
Automatisk skapande av dessa filer och filuppdateringar kallas scaffolding.
Det går inte att använda de autogenererade sidorna ännu eftersom databasen inte finns. Om du kör appen och väljer länken Filmapp visas ett Felmeddelande om att det inte går att öppna databasen eller att det inte finns någon sådan tabell: Felmeddelande om film .
Skapa appen för att kontrollera att det inte finns några fel.
Inledande migrering
EF Core Använd migreringsfunktionen för att skapa databasen. Migreringar är en uppsättning verktyg som skapar och uppdaterar en databas som matchar datamodellen.
På menyn Verktyg väljer du NuGet Package Manager>Konsol.
I Package Manager Console (PMC) anger du följande kommandon:
Add-Migration InitialCreate
Update-Database
- Add-Migration InitialCreate: Skapar en- Migrations/{timestamp}_InitialCreate.csmigreringsfil. Argumentet- InitialCreateär migreringsnamnet. Valfritt namn kan användas, men enligt konventionen väljs ett namn som beskriver migreringen. Eftersom det här är den första migreringen innehåller den genererade klassen kod för att skapa databasschemat. Databasschemat baseras på den modell som anges i- MvcMovieContextklassen.
- Update-Database: Uppdaterar databasen till den senaste migreringen, som föregående kommando skapade. Det här kommandot kör- Up-metoden i- Migrations/{time-stamp}_InitialCreate.csfilen, som skapar databasen.
Kommandot Update-Database genererar följande varning:
Ingen typ angavs för decimalkolumnen "Price" för entitetstypen "Film". Detta gör att värdena beskärs automatiskt om de inte får plats i standardprecisionen och skalan. Ange uttryckligen den SQL Server-kolumntyp som kan hantera alla värden med hjälp av "HasColumnType()".
Ignorera föregående varning, den åtgärdas i en senare handledning.
Mer information om PMC-verktygen för EF Corefinns i verktygsreferensEF Core – PMC i Visual Studio.
Testa appen
Kör appen och välj länken Filmapp .
Om du får ett undantag som liknar följande kan du ha missat Update-Database kommandot i migreringssteget:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Note
Du kanske inte kan ange decimaltecken i fältet Price. För att stödja jQuery-validering för språk som inte är engelska och som använder kommatecken (",") för en decimalpunkt och för datumformat som inte är US-English måste appen globaliseras. Globaliseringsinstruktioner finns i det här GitHub-problemet.
Granska den genererade databaskontextklassen och registreringen
Med EF Coreutförs dataåtkomst med hjälp av en modell. En modell består av entitetsklasser och ett kontextobjekt som representerar en session med databasen. Med kontextobjektet kan du köra frågor mot och spara data. Databaskontexten härleds från Microsoft.EntityFrameworkCore.DbContext och anger de entiteter som ska ingå i datamodellen.
Byggnadsställningar skapar databaskontextklassen Data/MvcMovieContext.cs :
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; }
    }
}
Föregående kod skapar en DbSet<Movie-egenskap> som representerar filmerna i databasen.
Beroendeinsprutning
ASP.NET Core skapas med beroendeinmatning (DI). Tjänster, till exempel databaskontexten, registreras med DI i Program.cs. Dessa tjänster tillhandahålls till komponenter som kräver dem via konstruktorparametrar.
              Controllers/MoviesController.cs I filen använder konstruktorn Dependency Injection för att injicera databaskontexten MvcMovieContext i kontrollern. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Scaffolding genererade följande markerade kod i Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
Konfigurationssystemet ASP.NET Core läser databasanslutningssträngen "MvcMovieContext".
Granska den genererade databasanslutningssträngen
Scaffolding lade till en anslutningssträng i appsettings.json filen:
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MvcMovieContext": "Data Source=MvcMovieContext-ea7a4069-f366-4742-bd1c-3f753a804ce1.db"
  }
}
För lokal utveckling läser konfigurationssystemet ASP.NET Core nyckeln från ConnectionString-filen.
Klassen InitialCreate
Granska migreringsfilen Migrations/{timestamp}_InitialCreate.cs :
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");
        }
    }
}
I koden ovan:
- 
              InitialCreate.Upskapar tabellen Film och konfigurerarIdsom primär nyckel.
- 
              InitialCreate.Downåterställer schemaändringarna som gjorts av migreringenUp.
Beroendeinmatning i kontrollanten
              Controllers/MoviesController.cs Öppna filen och granska konstruktorn:
public class MoviesController : Controller
{
    private readonly MvcMovieContext _context;
    public MoviesController(MvcMovieContext context)
    {
        _context = context;
    }
Konstruktorn använder beroendeinmatning för att mata in databaskontexten (MvcMovieContext) i kontrollanten. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Testa Skapa-sidan. Ange och skicka data.
Testa sidorna Redigera, Information och Ta bort .
Starkt skrivna modeller och @model direktivet
Tidigare i den här självstudien såg du hur en kontrollant kan skicka data eller objekt till en vy med hjälp av ViewData ordlistan. Ordlistan ViewData är ett dynamiskt objekt som ger ett bekvämt sent bundet sätt att skicka information till en vy.
MVC ger möjlighet att skicka starkt typerade modellobjekt till en vy. Med det här starkt typade tillvägagångssättet möjliggörs kompileringskontroll. Scaffolding-mekanismen överförde en starkt typad modell i klassen och vyerna i MoviesController.
Granska den genererade Details metoden i Controllers/MoviesController.cs filen:
// 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);
}
Parametern id skickas vanligtvis som routningsdata. Till exempel https://localhost:5001/movies/details/1 sätter:
- Kontrollern till kontrollern movies, det första URL-segmentet.
- Åtgärden för details, den andra URL-segmentet.
- Från idtill 1, det sista URL-segmentet.
              id Kan skickas med en frågesträng, som i följande exempel:
https://localhost:5001/movies/details?id=1
Parametern id definieras som en nullbar typ (int?) i de fall då id värdet inte anges.
Ett lambda-uttryck skickas till FirstOrDefaultAsync metoden för att välja filmentiteter som matchar routningsdata eller frågesträngsvärdet.
var movie = await _context.Movie
    .FirstOrDefaultAsync(m => m.Id == id);
Om en film hittas skickas en instans av Movie modellen till Details vyn:
return View(movie);
Granska innehållet i Views/Movies/Details.cshtml filen:
@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>
Instruktionen @model överst i vyfilen anger vilken typ av objekt som vyn förväntar sig. När filmkontrollanten skapades inkluderades följande @model instruktion:
@model MvcMovie.Models.Movie
Det här @model direktivet ger åtkomst till filmen som kontrollanten skickade till vyn. Objektet Model är starkt typat. I Details.cshtml-vyn skickar koden varje filmfält till DisplayNameFor och DisplayFor HTML-hjälpare med det starkt typerade Model-objektet. Metoderna Create och Edit vyerna skickar också ett Movie modellobjekt.
Granska Index.cshtml vyn och Index metoden i filmmodulens kontroll. Observera hur koden skapar ett List objekt när den anropar View metoden. Koden skickar den här Movies listan från Index åtgärdsmetoden till vyn:
// GET: Movies
public async Task<IActionResult> Index()
{
    return View(await _context.Movie.ToListAsync());
}
Koden returnerar probleminformation om Movie egenskapen för datakontexten är null.
När filmkontrollern skapades innehöll scaffold följande @model sats överst i Index.cshtml filen.
@model IEnumerable<MvcMovie.Models.Movie>
Direktivet @model ger åtkomst till listan över filmer som kontrollanten skickade till vyn med hjälp av ett Model objekt som är starkt skrivet. I vyn loopar koden till exempel Index.cshtml igenom filmerna med en foreach instruktion över det starkt typerade Model objektet:
@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>
Eftersom objektet Model är starkt skrivet som ett IEnumerable<Movie> objekt, skrivs varje objekt i loopen som Movie. Kompilatorn validerar bland annat de typer som används i koden.
Ytterligare resurser
I den här självstudien har klasser lagts till för att hantera filmer i en databas. Dessa klasser är "Model"-delen av MVC-appen.
Dessa modellklasser används med Entity Framework Core (EF Core) för att arbeta med en databas. EF Core är ett ramverk för objektrelationsmappning (ORM) som förenklar den dataåtkomstkod som du måste skriva.
De modellklasser som skapas kallas POCO-klasser , från Plain Old CLR Objects. POCO-klasser har inget beroende av EF Core. De definierar bara egenskaperna för de data som ska lagras i databasen.
I den här självstudien skapas modellklasser först och EF Core skapar databasen.
Lägga till en datamodellklass
Högerklicka på mappen >Lägg till>klass. Ge filen namnet Movie.cs.
Uppdatera filen Models/Movie.cs med följande kod:
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; }
    }
}
Klassen Movie innehåller ett Id fält som krävs av databasen för den primära nyckeln.
Attributet DataType på ReleaseDate anger typen av data (Date). Med det här attributet:
- Användaren behöver inte ange tidsinformation i datumfältet.
- Endast datumet visas, inte tidsinformation.
DataAnnotations behandlas i en senare handledning.
Frågetecknet efter string anger att egenskapen är null. För mer information, se nullbara referenstyper.
Lägga till NuGet-paket
På menyn Verktyg väljer du NuGet Package Manager>Package Manager Console (PMC).
               
              
            
Kör följande kommando i PMC:
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.SqlServer
De föregående kommandona lägger till:
- EF Core SQL Server-leverantören. Providerpaketet installerar EF Core paketet som ett beroende.
- De verktyg som används av de paket som installeras automatiskt i scaffoldingssteget, senare i handledningen.
Skapa projektet som en kontroll av kompilatorfel.
Strukturera filmsidor
Använd verktyget scaffolding för att skapa Create, Read, Updateoch Delete (CRUD) sidor för filmmodellen.
Högerklicka på mappen Controllers i Solution Explorer och välj Lägg till > nytt autogenererat objekt.
               
              
            
I dialogrutan Skapa mall väljer du MVC-kontroller med vyer och som använder Entity Framework > Lägg till.
               
              
            
Slutför dialogrutan Lägg till MVC-styrenhet med vyer med hjälp av entitetsramverket :
- I listrutan Modellklass väljer du Film (MvcMovie.Models).
- I raden Datakontextklass väljer du tecknet + (plus).
- I dialogrutan Lägg till datakontext genereras klassnamnet MvcMovie.Data.MvcMovieContext .
- Välj Lägg till.
 
- Vyer och kontrollantnamn: Behåll standardvärdet.
- Välj Lägg till.
               
              
            
Om du får ett felmeddelande väljer du Lägg till en andra gång för att försöka igen.
Scaffolding uppdaterar följande:
- Infogar nödvändiga paketreferenser i MvcMovie.csprojprojektfilen.
- Registrerar databaskontexten Program.csi filen.
- Lägger till en databasanslutningssträng i appsettings.jsonfilen.
Scaffolding skapar följande:
- En filmkontroller: Controllers/MoviesController.cs
- 
              Razor visa filer för sidorna Skapa, Ta bort, Information, Redigera och Index : Views/Movies/*.cshtml
- En databaskontextklass: Data/MvcMovieContext.cs
Automatisk skapande av dessa filer och filuppdateringar kallas scaffolding.
Det går inte att använda de autogenererade sidorna ännu eftersom databasen inte finns. Om du kör appen och väljer länken Filmapp visas ett Felmeddelande om att det inte går att öppna databasen eller att det inte finns någon sådan tabell: Felmeddelande om film .
Skapa appen
Skapa appen. Kompilatorn genererar flera varningar om hur null värden hanteras. Mer information finns i det här GitHub-problemet och referenstyper som kan ogiltigförklaras .
För att ta bort varningarna från nullbara referenstyper, ta bort följande rad från MvcMovie.csproj-filen:
<Nullable>enable</Nullable>
Vi hoppas kunna åtgärda problemet i nästa version.
Inledande migrering
EF Core Använd migreringsfunktionen för att skapa databasen. Migreringar är en uppsättning verktyg som skapar och uppdaterar en databas som matchar datamodellen.
På menyn Verktyg väljer du NuGet Package Manager>Konsol.
I Package Manager Console (PMC) anger du följande kommandon:
Add-Migration InitialCreate
Update-Database
- Add-Migration InitialCreate: Skapar en- Migrations/{timestamp}_InitialCreate.csmigreringsfil. Argumentet- InitialCreateär migreringsnamnet. Valfritt namn kan användas, men enligt konventionen väljs ett namn som beskriver migreringen. Eftersom det här är den första migreringen innehåller den genererade klassen kod för att skapa databasschemat. Databasschemat baseras på den modell som anges i- MvcMovieContextklassen.
- Update-Database: Uppdaterar databasen till den senaste migreringen, som föregående kommando skapade. Det här kommandot kör- Up-metoden i- Migrations/{time-stamp}_InitialCreate.csfilen, som skapar databasen.
Kommandot Update-Database genererar följande varning:
Ingen typ angavs för decimalkolumnen "Price" för entitetstypen "Film". Detta gör att värdena beskärs automatiskt om de inte får plats i standardprecisionen och skalan. Ange uttryckligen den SQL Server-kolumntyp som kan hantera alla värden med hjälp av "HasColumnType()".
Ignorera föregående varning, den åtgärdas i en senare handledning.
Mer information om PMC-verktygen för EF Corefinns i verktygsreferensEF Core – PMC i Visual Studio.
Testa appen
Kör appen och välj länken Filmapp .
Om du får ett undantag som liknar följande kan du ha missat migreringssteget:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Note
Du kanske inte kan ange decimaltecken i fältet Price. För att stödja jQuery-validering för språk som inte är engelska och som använder kommatecken (",") för en decimalpunkt och för datumformat som inte är US-English måste appen globaliseras. Globaliseringsinstruktioner finns i det här GitHub-problemet.
Granska den genererade databaskontextklassen och registreringen
Med EF Coreutförs dataåtkomst med hjälp av en modell. En modell består av entitetsklasser och ett kontextobjekt som representerar en session med databasen. Med kontextobjektet kan du köra frågor mot och spara data. Databaskontexten härleds från Microsoft.EntityFrameworkCore.DbContext och anger de entiteter som ska ingå i datamodellen.
Byggnadsställningar skapar databaskontextklassen Data/MvcMovieContext.cs :
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; }
    }
}
Föregående kod skapar en DbSet<Movie-egenskap> som representerar filmerna i databasen.
Beroendeinsprutning
ASP.NET Core skapas med beroendeinmatning (DI). Tjänster, till exempel databaskontexten, registreras med DI i Program.cs. Dessa tjänster tillhandahålls till komponenter som kräver dem via konstruktorparametrar.
              Controllers/MoviesController.cs I filen använder konstruktorn Dependency Injection för att injicera databaskontexten MvcMovieContext i kontrollern. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Scaffolding genererade följande markerade kod i Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
Konfigurationssystemet ASP.NET Core läser databasanslutningssträngen "MvcMovieContext".
Granska den genererade databasanslutningssträngen
Scaffolding lade till en anslutningssträng i appsettings.json filen:
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-7dc5;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}
För lokal utveckling läser konfigurationssystemet ASP.NET Core nyckeln från ConnectionString-filen.
Klassen InitialCreate
Granska migreringsfilen Migrations/{timestamp}_InitialCreate.cs :
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");
        }
    }
}
I koden ovan:
- 
              InitialCreate.Upskapar tabellen Film och konfigurerarIdsom primär nyckel.
- 
              InitialCreate.Downåterställer schemaändringarna som gjorts av migreringenUp.
Beroendeinmatning i kontrollanten
              Controllers/MoviesController.cs Öppna filen och granska konstruktorn:
public class MoviesController : Controller
{
    private readonly MvcMovieContext _context;
    public MoviesController(MvcMovieContext context)
    {
        _context = context;
    }
Konstruktorn använder beroendeinmatning för att mata in databaskontexten (MvcMovieContext) i kontrollanten. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Testa Skapa-sidan. Ange och skicka data.
Testa sidorna Redigera, Information och Ta bort .
Starkt skrivna modeller och @model direktivet
Tidigare i den här självstudien såg du hur en kontrollant kan skicka data eller objekt till en vy med hjälp av ViewData ordlistan. Ordlistan ViewData är ett dynamiskt objekt som ger ett bekvämt sent bundet sätt att skicka information till en vy.
MVC ger möjlighet att skicka starkt typerade modellobjekt till en vy. Med det här starkt typade tillvägagångssättet möjliggörs kompileringskontroll. Scaffolding-mekanismen överförde en starkt typad modell i klassen och vyerna i MoviesController.
Granska den genererade Details metoden i Controllers/MoviesController.cs filen:
// 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);
}
Parametern id skickas vanligtvis som routningsdata. Till exempel https://localhost:5001/movies/details/1 sätter:
- Kontrollern till kontrollern movies, det första URL-segmentet.
- Åtgärden för details, den andra URL-segmentet.
- Från idtill 1, det sista URL-segmentet.
              id Kan skickas med en frågesträng, som i följande exempel:
https://localhost:5001/movies/details?id=1
Parametern id definieras som en nullbar typ (int?) i de fall då id värdet inte anges.
Ett lambda-uttryck skickas till FirstOrDefaultAsync metoden för att välja filmentiteter som matchar routningsdata eller frågesträngsvärdet.
var movie = await _context.Movie
    .FirstOrDefaultAsync(m => m.Id == id);
Om en film hittas skickas en instans av Movie modellen till Details vyn:
return View(movie);
Granska innehållet i Views/Movies/Details.cshtml filen:
@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>
Instruktionen @model överst i vyfilen anger vilken typ av objekt som vyn förväntar sig. När filmkontrollanten skapades inkluderades följande @model instruktion:
@model MvcMovie.Models.Movie
Det här @model direktivet ger åtkomst till filmen som kontrollanten skickade till vyn. Objektet Model är starkt typat. I Details.cshtml-vyn skickar koden varje filmfält till DisplayNameFor och DisplayFor HTML-hjälpare med det starkt typerade Model-objektet. Metoderna Create och Edit vyerna skickar också ett Movie modellobjekt.
Granska Index.cshtml vyn och Index metoden i filmmodulens kontroll. Observera hur koden skapar ett List objekt när den anropar View metoden. Koden skickar den här Movies listan från Index åtgärdsmetoden till vyn:
// GET: Movies
public async Task<IActionResult> Index()
{
    return View(await _context.Movie.ToListAsync());
}
När filmkontrollern skapades innehöll scaffold följande @model sats överst i Index.cshtml filen.
@model IEnumerable<MvcMovie.Models.Movie>
Direktivet @model ger åtkomst till listan över filmer som kontrollanten skickade till vyn med hjälp av ett Model objekt som är starkt skrivet. I vyn loopar koden till exempel Index.cshtml igenom filmerna med en foreach instruktion över det starkt typerade Model objektet:
@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>
Eftersom objektet Model är starkt skrivet som ett IEnumerable<Movie> objekt, skrivs varje objekt i loopen som Movie. Kompilatorn validerar bland annat de typer som används i koden.
Ytterligare resurser
I den här självstudien har klasser lagts till för att hantera filmer i en databas. Dessa klasser är "Model"-delen av MVC-appen.
Dessa modellklasser används med Entity Framework Core (EF Core) för att arbeta med en databas. EF Core är ett ramverk för objektrelationsmappning (ORM) som förenklar den dataåtkomstkod som du måste skriva.
De modellklasser som skapas kallas POCO-klasser , från Plain Old CLR Objects. POCO-klasser har inget beroende av EF Core. De definierar bara egenskaperna för de data som ska lagras i databasen.
I den här självstudien skapas modellklasser först och EF Core skapar databasen.
Lägga till en datamodellklass
Högerklicka på mappen >Lägg till>klass. Ge filen namnet Movie.cs.
Uppdatera filen Models/Movie.cs med följande kod:
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; }
    }
}
Klassen Movie innehåller ett Id fält som krävs av databasen för den primära nyckeln.
Attributet DataType på ReleaseDate anger typen av data (Date). Med det här attributet:
- Användaren behöver inte ange tidsinformation i datumfältet.
- Endast datumet visas, inte tidsinformation.
DataAnnotations behandlas i en senare handledning.
Lägga till NuGet-paket
På menyn Verktyg väljer du NuGet Package Manager>Package Manager Console (PMC).
               
              
            
Kör följande kommando i PMC:
Install-Package Microsoft.EntityFrameworkCore.Design
De föregående kommandona lägger till:
- EF Core SQL Server-leverantören. Providerpaketet installerar EF Core paketet som ett beroende.
- De verktyg som används av de paket som installeras automatiskt i scaffoldingssteget, senare i handledningen.
Skapa projektet som en kontroll av kompilatorfel.
Strukturera filmsidor
Använd verktyget scaffolding för att skapa Create, Read, Updateoch Delete (CRUD) sidor för filmmodellen.
Högerklicka på mappen Controllers i Solution Explorer och välj Lägg till > nytt autogenererat objekt.
               
              
            
I dialogrutan Skapa mall väljer du MVC-kontroller med vyer och som använder Entity Framework > Lägg till.
               
              
            
Slutför dialogrutan Lägg till MVC-styrenhet med vyer med hjälp av entitetsramverket :
- I listrutan Modellklass väljer du Film (MvcMovie.Models).
- I raden Datakontextklass väljer du tecknet + (plus).
- I dialogrutan Lägg till datakontext genereras klassnamnet MvcMovie.Data.MvcMovieContext .
- Välj Lägg till.
 
- Vyer och kontrollantnamn: Behåll standardvärdet.
- Välj Lägg till.
               
              
            
Scaffolding uppdaterar följande:
- Infogar nödvändiga paketreferenser i MvcMovie.csprojprojektfilen.
- Registrerar databaskontexten Startup.ConfigureServicesiStartup.csfilen.
- Lägger till en databasanslutningssträng i appsettings.jsonfilen.
Scaffolding skapar följande:
- En filmkontroller: Controllers/MoviesController.cs
- 
              Razor visa filer för sidorna Skapa, Ta bort, Information, Redigera och Index : Views/Movies/*.cshtml
- En databaskontextklass: Data/MvcMovieContext.cs
Automatisk skapande av dessa filer och filuppdateringar kallas för strukturskapande.
Det går inte att använda de autogenererade sidorna ännu eftersom databasen inte finns. Om du kör appen och väljer länken Filmapp visas ett Felmeddelande om att det inte går att öppna databasen eller att det inte finns någon sådan tabell: Felmeddelande om film .
Inledande migrering
EF Core Använd migreringsfunktionen för att skapa databasen. Migreringar är en uppsättning verktyg som skapar och uppdaterar en databas för att matcha datamodellen.
På menyn Verktyg väljer du NuGet Package Manager>Konsol.
I Package Manager Console (PMC) anger du följande kommandon:
Add-Migration InitialCreate
Update-Database
- Add-Migration InitialCreate: Skapar en- Migrations/{timestamp}_InitialCreate.csmigreringsfil. Argumentet- InitialCreateär migreringsnamnet. Valfritt namn kan användas, men enligt konventionen väljs ett namn som beskriver migreringen. Eftersom det här är den första migreringen innehåller den genererade klassen kod för att skapa databasschemat. Databasschemat baseras på den modell som anges i- MvcMovieContextklassen.
- Update-Database: Uppdaterar databasen till den senaste migreringen, som föregående kommando skapade. Det här kommandot kör- Up-metoden i- Migrations/{time-stamp}_InitialCreate.csfilen, som skapar databasen.
Kommandot Update-Database genererar följande varning:
Ingen typ angavs för decimalkolumnen "Price" för entitetstypen "Film". Detta gör att värdena beskärs automatiskt om de inte får plats i standardprecisionen och skalan. Ange uttryckligen den SQL Server-kolumntyp som kan hantera alla värden med hjälp av "HasColumnType()".
Ignorera föregående varning, den åtgärdas i en senare handledning.
Mer information om PMC-verktygen för EF Corefinns i verktygsreferensEF Core – PMC i Visual Studio.
Testa appen
Kör appen och välj länken Filmapp .
Om du får ett undantag som liknar följande kan du ha missat migreringssteget:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Note
Du kanske inte kan ange decimaltecken i fältet Price. För att stödja jQuery-validering för språk som inte är engelska och som använder kommatecken (",") för en decimalpunkt och för datumformat som inte är US-English måste appen globaliseras. Globaliseringsinstruktioner finns i det här GitHub-problemet.
Granska den genererade databaskontextklassen och registreringen
Med EF Coreutförs dataåtkomst med hjälp av en modell. En modell består av entitetsklasser och ett kontextobjekt som representerar en session med databasen. Med kontextobjektet kan du köra frågor mot och spara data. Databaskontexten härleds från Microsoft.EntityFrameworkCore.DbContext och anger de entiteter som ska ingå i datamodellen.
Byggnadsställningar skapar databaskontextklassen Data/MvcMovieContext.cs :
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; }
    }
}
Föregående kod skapar en DbSet<Movie-egenskap> som representerar filmerna i databasen.
ASP.NET Core skapas med beroendeinmatning (DI). Tjänster, till exempel databaskontexten, måste registreras med DI i Startup. Komponenter som kräver dessa tjänster tillhandahålls via konstruktorparametrar.
              Controllers/MoviesController.cs I filen använder konstruktorn Dependency Injection för att injicera databaskontexten MvcMovieContext i kontrollern. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Scaffolding genererade följande markerade kod i Startup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddDbContext<MvcMovieContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}
Konfigurationssystemet ASP.NET Core läser databasanslutningssträngen "MvcMovieContext".
Granska den genererade databasanslutningssträngen
Scaffolding lade till en anslutningssträng i appsettings.json filen:
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}
För lokal utveckling läser konfigurationssystemet ASP.NET Core nyckeln från ConnectionString-filen.
Klassen InitialCreate
Granska migreringsfilen Migrations/{timestamp}_InitialCreate.cs :
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");
    }
}
I koden ovan:
- 
              InitialCreate.Upskapar tabellen Film och konfigurerarIdsom primär nyckel.
- 
              InitialCreate.Downåterställer schemaändringarna som gjorts av migreringenUp.
Beroendeinmatning i kontrollanten
              Controllers/MoviesController.cs Öppna filen och granska konstruktorn:
public class MoviesController : Controller
{
    private readonly MvcMovieContext _context;
    public MoviesController(MvcMovieContext context)
    {
        _context = context;
    }
Konstruktorn använder beroendeinmatning för att mata in databaskontexten (MvcMovieContext) i kontrollanten. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Testa Skapa-sidan. Ange och skicka data.
Testa sidorna Redigera, Information och Ta bort .
Starkt skrivna modeller och @model direktivet
Tidigare i den här självstudien såg du hur en kontrollant kan skicka data eller objekt till en vy med hjälp av ViewData ordlistan. Ordlistan ViewData är ett dynamiskt objekt som ger ett bekvämt sent bundet sätt att skicka information till en vy.
MVC ger möjlighet att skicka starkt typerade modellobjekt till en vy. Med det här starkt typade tillvägagångssättet möjliggörs kompileringskontroll. Scaffolding-mekanismen överförde en starkt typad modell i klassen och vyerna i MoviesController.
Granska den genererade Details metoden i Controllers/MoviesController.cs filen:
// 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);
}
Parametern id skickas vanligtvis som routningsdata. Till exempel https://localhost:5001/movies/details/1 sätter:
- Kontrollern till kontrollern movies, det första URL-segmentet.
- Åtgärden för details, den andra URL-segmentet.
- Från idtill 1, det sista URL-segmentet.
              id Kan skickas med en frågesträng, som i följande exempel:
https://localhost:5001/movies/details?id=1
Parametern id definieras som en nullbar typ (int?) i de fall då id värdet inte anges.
Ett lambda-uttryck skickas till FirstOrDefaultAsync metoden för att välja filmentiteter som matchar routningsdata eller frågesträngsvärdet.
var movie = await _context.Movie
    .FirstOrDefaultAsync(m => m.Id == id);
Om en film hittas skickas en instans av Movie modellen till Details vyn:
return View(movie);
Granska innehållet i Views/Movies/Details.cshtml filen:
@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>
Instruktionen @model överst i vyfilen anger vilken typ av objekt som vyn förväntar sig. När filmkontrollanten skapades inkluderades följande @model instruktion:
@model MvcMovie.Models.Movie
Det här @model direktivet ger åtkomst till filmen som kontrollanten skickade till vyn. Objektet Model är starkt typat. I Details.cshtml-vyn skickar koden varje filmfält till DisplayNameFor och DisplayFor HTML-hjälpare med det starkt typerade Model-objektet. Metoderna Create och Edit vyerna skickar också ett Movie modellobjekt.
Granska Index.cshtml vyn och Index metoden i filmmodulens kontroll. Observera hur koden skapar ett List objekt när den anropar View metoden. Koden skickar den här Movies listan från Index åtgärdsmetoden till vyn:
// GET: Movies
public async Task<IActionResult> Index()
{
    return View(await _context.Movie.ToListAsync());
}
När filmkontrollern skapades innehöll scaffold följande @model sats överst i Index.cshtml filen.
@model IEnumerable<MvcMovie.Models.Movie>
Direktivet @model ger åtkomst till listan över filmer som kontrollanten skickade till vyn med hjälp av ett Model objekt som är starkt skrivet. I vyn loopar koden till exempel Index.cshtml igenom filmerna med en foreach instruktion över det starkt typerade Model objektet:
@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>
Eftersom objektet Model är starkt skrivet som ett IEnumerable<Movie> objekt, skrivs varje objekt i loopen som Movie. Kompilatorn validerar bland annat de typer som används i koden.
SQL-loggning av Entity Framework Core
Loggningskonfiguration tillhandahålls ofta av avsnittet Logging i appsettings.{Environment}.json filer. Om du vill logga SQL-instruktioner lägger du till "Microsoft.EntityFrameworkCore.Database.Command": "Information" i filen appsettings.Development.json:
{
  "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": "*"
}
Med föregående JSON visas SQL-uttryck på kommandoraden och i Visual Studio-utdatafönstret.
Mer information finns i Loggning i .NET och ASP.NET Core och det här GitHub-problemet.
Ytterligare resurser
I den här självstudien har klasser lagts till för att hantera filmer i en databas. Dessa klasser är "Model"-delen av MVC-appen.
Dessa modellklasser används med Entity Framework Core (EF Core) för att arbeta med en databas. EF Core är ett ramverk för objektrelationsmappning (ORM) som förenklar den dataåtkomstkod som du måste skriva.
De modellklasser som skapas kallas POCO-klasser , från Plain Old CLR Objects. POCO-klasser har inget beroende av EF Core. De definierar bara egenskaperna för de data som ska lagras i databasen.
I den här självstudien skapas modellklasser först och EF Core skapar databasen.
Lägga till en datamodellklass
Högerklicka på mappen >Lägg till>klass. Ge filen namnet Movie.cs.
Uppdatera filen Movie.cs med följande kod:
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; }
    }
}
Klassen Movie innehåller ett Id fält som krävs av databasen för den primära nyckeln.
Attributet DataType på ReleaseDate anger typen av data (Date). Med det här attributet:
- Användaren behöver inte ange tidsinformation i datumfältet.
- Endast datumet visas, inte tidsinformation.
DataAnnotations behandlas i en senare handledning.
Lägga till NuGet-paket
På menyn Verktyg väljer du NuGet Package Manager>Package Manager Console (PMC).
               
              
            
Kör följande kommando i PMC:
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Föregående kommando lägger till EF Core SQL Server-providern. Providerpaketet installerar EF Core paketet som ett beroende. Ytterligare paket installeras automatiskt i scaffoldingssteget senare i självstudien.
Skapa en databaskontextklass
En databaskontextklass krävs för att samordna EF Core funktioner (Skapa, Läsa, Uppdatera, Ta bort) för Movie modellen. Databaskontexten härleds från Microsoft.EntityFrameworkCore.DbContext och anger de entiteter som ska ingå i datamodellen.
Skapa en datamapp.
Lägg till en Data/MvcMovieContext.cs fil med följande kod:
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; }
    }
}
Föregående kod skapar egenskapen DbSet<Movie> för entitetsuppsättningen. I Entity Framework-terminologi motsvarar en entitetsuppsättning vanligtvis en databastabell. En entitet motsvarar en rad i tabellen.
Registrera databaskontexten
ASP.NET Core skapas med beroendeinmatning (DI). Tjänster (till exempel DB-kontexten EF Core ) måste registreras med DI under programstarten. Komponenter som kräver dessa tjänster (till exempel Razor Pages) tillhandahålls via konstruktorparametrar. Konstruktorkoden som hämtar en DB-kontextinstans visas senare i självstudien. I det här avsnittet registrerar du databaskontexten med DI-containern.
Lägg till följande using-instruktioner högst upp i Startup.cs:
using MvcMovie.Data;
using Microsoft.EntityFrameworkCore;
Lägg till följande markerade kod i Startup.ConfigureServices:
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddDbContext<MvcMovieContext>(options =>
    options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}
Namnet på anslutningssträngen skickas till kontexten genom att anropa en metod för ett DbContextOptions-objekt. För lokal utveckling läser konfigurationssystemet ASP.NET Core anslutningssträngen appsettings.json från filen.
Granska databasanslutningssträngen
Lägg till en anslutningssträng i appsettings.json filen:
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}
Skapa projektet som en kontroll av kompilatorfel.
Strukturera filmsidor
Använd verktyget scaffolding för att skapa CRUD-sidor (Create, Read, Update och Delete) för filmmodellen.
I Solution Explorer högerklickar du på mappen Controllers och väljer >.
               
              
            
I dialogrutan Skapa mall väljer du MVC-kontroller med vyer och som använder Entity Framework > Lägg till.
               
              
            
Slutför dialogrutan Lägg till kontrollant :
- Modellklass:Film (MvcMovie.Models)
- Datakontextklass:MvcMovieContext (MvcMovie.Data)
               
              
            
- Visningar: Behåll standardvärdet för varje alternativ markerat
- Kontrollernamn: Behåll MoviesController (standard)
- Välj Lägg till
Visual Studio skapar:
- En filmkontrollant (Controllers/MoviesController.cs)
- Razor visa filer för Skapa, Ta bort, Detaljer, Redigera och Index-sidor (*Views/Movies/`.cshtml`)
Automatisk skapande av dessa filer kallas stomme.
Du kan inte använda de genererade sidorna ännu eftersom databasen inte finns. Om du kör appen och klickar på länken Filmapp får du ett felmeddelande om att det inte går att öppna databasen eller att det inte finns någon sådan tabell: Felmeddelande om film .
Inledande migrering
EF Core Använd migreringsfunktionen för att skapa databasen. Migreringar är en uppsättning verktyg som gör att du kan skapa och uppdatera en databas så att den matchar din datamodell.
På menyn Verktyg väljer du NuGet Package Manager>Package Manager Console (PMC).
I PMC anger du följande kommandon:
Add-Migration InitialCreate
Update-Database
- Add-Migration InitialCreate: Skapar en- Migrations/{timestamp}_InitialCreate.csmigreringsfil. Argumentet- InitialCreateär migreringsnamnet. Valfritt namn kan användas, men enligt konventionen väljs ett namn som beskriver migreringen. Eftersom det här är den första migreringen innehåller den genererade klassen kod för att skapa databasschemat. Databasschemat baseras på den modell som anges i- MvcMovieContextklassen.
- Update-Database: Uppdaterar databasen till den senaste migreringen, som föregående kommando skapade. Det här kommandot kör- Up-metoden i- Migrations/{time-stamp}_InitialCreate.csfilen, som skapar databasen.- Kommandot för databasuppdatering genererar följande varning: - Ingen typ angavs för decimalkolumnen "Price" för entitetstypen "Film". Detta gör att värdena beskärs automatiskt om de inte får plats i standardprecisionen och skalan. Ange uttryckligen den SQL Server-kolumntyp som kan hantera alla värden med hjälp av "HasColumnType()". - Du kan ignorera den varningen. Den kommer att åtgärdas i en senare handledning. 
Mer information om PMC-verktygen för EF Corefinns i verktygsreferensEF Core – PMC i Visual Studio.
Klassen InitialCreate
Granska migreringsfilen Migrations/{timestamp}_InitialCreate.cs :
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");
    }
}
Metoden Up skapar tabellen Film och konfigurerar Id som primärnyckel. Metoden Down återställer schemaändringarna som gjorts av migreringen Up .
Testa appen
- Kör appen och klicka på länken Filmapp . - Om du får ett undantag som liknar något av följande: 
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Du missade förmodligen migreringssteget.
- Testa Skapa-sidan. Ange och skicka data. - Note - Du kanske inte kan ange decimaltecken i fältet - Price. För att stödja jQuery-validering för språk som inte är engelska och som använder kommatecken (",") för en decimalpunkt och för datumformat som inte är US-English måste appen globaliseras. Globaliseringsinstruktioner finns i det här GitHub-problemet.
- Testa sidorna Redigera, Information och Ta bort . 
Beroendeinmatning i kontrollanten
              Controllers/MoviesController.cs Öppna filen och granska konstruktorn:
public class MoviesController : Controller
{
    private readonly MvcMovieContext _context;
    public MoviesController(MvcMovieContext context)
    {
        _context = context;
    }
Konstruktorn använder beroendeinmatning för att mata in databaskontexten (MvcMovieContext) i kontrollanten. Databaskontexten används i var och en av de CRUD- metoderna i kontrollanten.
Starkt skrivna modeller och nyckelordet @model
Tidigare i den här självstudien såg du hur en kontrollant kan skicka data eller objekt till en vy med hjälp av ViewData ordlistan. Ordlistan ViewData är ett dynamiskt objekt som ger ett bekvämt sent bundet sätt att skicka information till en vy.
MVC ger också möjlighet att skicka starkt typerade modellobjekt till en vy. Med det här starkt typade tillvägagångssättet möjliggörs kompileringskontroll. Scaffoldingsystemet använde den här metoden (dvs. att skicka en starkt typad modell) med MoviesController-klassen och vyerna.
Granska den genererade Details metoden i Controllers/MoviesController.cs filen:
// 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);
}
Parametern id skickas vanligtvis som routningsdata. 
              https://localhost:5001/movies/details/1 Exempeluppsättningar:
- Kontrollern till kontroller movies(det första URL-segmentet).
- Åtgärden för details(det andra URL-segmentet).
- ID:t till 1 (det sista URL-segmentet).
Du kan också skicka in id med en frågesträng på följande sätt:
https://localhost:5001/movies/details?id=1
Parametern id definieras som en nullbar typ (int?) om ett ID-värde inte anges.
Ett lambda-uttryck skickas till FirstOrDefaultAsync för att välja filmentiteter som matchar routedata eller frågesträngsvärdet.
var movie = await _context.Movie
    .FirstOrDefaultAsync(m => m.Id == id);
Om en film hittas skickas en instans av Movie modellen till Details vyn:
return View(movie);
Granska innehållet i Views/Movies/Details.cshtml filen:
@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>
Instruktionen @model överst i vyfilen anger vilken typ av objekt som vyn förväntar sig. När filmkontrollanten skapades inkluderades följande @model instruktion:
@model MvcMovie.Models.Movie
Det här @model direktivet ger åtkomst till filmen som kontrollanten skickade till vyn. Objektet Model är starkt typat. I Details.cshtml-vyn skickar koden varje filmfält till DisplayNameFor och DisplayFor HTML-hjälpare med det starkt typerade Model-objektet. Metoderna Create och Edit vyerna skickar också ett Movie modellobjekt.
Granska Index.cshtml vyn och Index metoden i filmmodulens kontroll. Observera hur koden skapar ett List objekt när den anropar View metoden. Koden skickar den här Movies listan från Index åtgärdsmetoden till vyn:
// GET: Movies
public async Task<IActionResult> Index()
{
    return View(await _context.Movie.ToListAsync());
}
När filmkontrollern skapades innehöll scaffold följande @model sats överst i Index.cshtml filen.
@model IEnumerable<MvcMovie.Models.Movie>
Med @model direktivet kan du komma åt listan över filmer som kontrollanten skickade till vyn med hjälp av ett Model objekt som är starkt skrivet. I vyn loopar koden till exempel Index.cshtml igenom filmerna med en foreach instruktion över det starkt typerade Model objektet:
@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>
Eftersom objektet Model är starkt typat (som ett IEnumerable<Movie>-objekt) anges varje objekt i loopen som Movie. Det innebär bland annat att du får kompileringstidskontroll av koden.
Ytterligare resurser
ASP.NET Core
 
              
            