Część 4. Dodawanie modelu do aplikacji MVC platformy ASP.NET Core
Uwaga
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Ważne
Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Przez Rick Anderson i Jon P Smith.
W tym samouczku klasy są dodawane do zarządzania filmami w bazie danych. Te klasy są częścią "odel" aplikacji MVC.
Te klasy modeli są używane z programem Entity Framework Core (EF Core) do pracy z bazą danych. EF Core to struktura mapowania relacyjnego (ORM, object-relational mapping), która upraszcza kod dostępu do danych, który trzeba napisać.
Utworzone klasy modeli są nazywane klasami POCO z Plain Old CLR Objects. Klasy POCO nie mają żadnej zależności od EF Coreklasy . Definiują tylko właściwości danych, które mają być przechowywane w bazie danych.
W tym samouczku klasy modeli są tworzone najpierw i EF Core tworzy bazę danych.
Dodawanie klasy modelu danych
Kliknij prawym przyciskiem myszy folder >Models Dodaj>klasę. Nazwij plik Movie.cs
.
Models/Movie.cs
Zaktualizuj plik przy użyciu następującego kodu:
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; }
}
Klasa Movie
zawiera Id
pole wymagane przez bazę danych dla klucza podstawowego.
Atrybut DataType on ReleaseDate
określa typ danych (Date
). Za pomocą tego atrybutu:
- Użytkownik nie musi wprowadzać informacji o godzinie w polu daty.
- Wyświetlana jest tylko data, a nie informacje o godzinie.
Adnotacje danych zostały omówione w późniejszym samouczku.
Znak zapytania po string
wskazuje, że właściwość jest dopuszczana do wartości null. Aby uzyskać więcej informacji, zobacz Typy referencyjne dopuszczane do wartości null.
Dodawanie pakietów NuGet
Program Visual Studio automatycznie instaluje wymagane pakiety.
Skompiluj projekt jako sprawdzenie błędów kompilatora.
Strony filmów szkieletowych
Narzędzie do tworzenia szkieletów umożliwia tworzenie Create
stron , Read
, Update
i Delete
(CRUD) dla modelu filmu.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Controllers i wybierz polecenie Dodaj > nowy element szkieletowy.
W oknie dialogowym Dodawanie nowego elementu szkieletu:
- W okienku po lewej stronie wybierz pozycję Zainstalowane>wspólne>MVC.
- Wybierz pozycję Kontroler MVC z widokami przy użyciu platformy Entity Framework.
- Wybierz Dodaj.
Ukończ okno dialogowe Dodawanie kontrolera MVC z widokami przy użyciu okna dialogowego Entity Framework:
- Z listy rozwijanej Klasa modelu wybierz pozycję Movie (MvcFilm.Models).
- W wierszu Klasy kontekstu danych wybierz + znak (plus).
- W oknie dialogowym Dodawanie kontekstu danych jest generowana nazwa klasy MvcFilm.Data.MvcTextContext.
- Wybierz Dodaj.
- Z listy rozwijanej Dostawca bazy danych wybierz pozycję SQL Server.
- Widoki i nazwa kontrolera: zachowaj wartość domyślną.
- Wybierz Dodaj.
Jeśli zostanie wyświetlony komunikat o błędzie, wybierz pozycję Dodaj po raz drugi, aby spróbować ponownie.
Tworzenie szkieletu dodaje następujące pakiety:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
Tworzenie szkieletu powoduje utworzenie następujących elementów:
- Kontroler filmów:
Controllers/MoviesController.cs
- Razor wyświetl pliki dla stron Tworzenie, Usuwanie, Szczegóły, Edytowanie i Indeks :
Views/Movies/*.cshtml
- Klasa kontekstu bazy danych:
Data/MvcMovieContext.cs
Tworzenie szkieletu aktualizuje następujące elementy:
- Wstawia wymagane odwołania do pakietu w
MvcMovie.csproj
pliku projektu. - Rejestruje kontekst bazy danych w
Program.cs
pliku. - Dodaje parametry połączenia bazy danych do
appsettings.json
pliku.
Automatyczne tworzenie tych plików i aktualizacji plików jest nazywane tworzeniem szkieletów.
Nie można jeszcze używać stron szkieletowych, ponieważ baza danych nie istnieje. Uruchomienie aplikacji i wybranie linku Aplikacja filmowa powoduje otwarcie bazy danych lub brak takiej tabeli: komunikat o błędzie Filmu .
Skompiluj aplikację, aby sprawdzić, czy nie ma żadnych błędów.
Migracja początkowa
EF CoreUżyj funkcji Migracje, aby utworzyć bazę danych. Migracje to zestaw narzędzi, które tworzą i aktualizują bazę danych w celu dopasowania ich do modelu danych.
Z menu Narzędzia wybierz pozycję NuGet Menedżer pakietów> Menedżer pakietów Konsola .
W konsoli Menedżer pakietów (PMC) wprowadź następujące polecenie:
Add-Migration InitialCreate
Add-Migration InitialCreate
: generujeMigrations/{timestamp}_InitialCreate.cs
plik migracji. ArgumentemInitialCreate
jest nazwa migracji. Można użyć dowolnej nazwy, ale zgodnie z konwencją wybrana jest nazwa opisującą migrację. Ponieważ jest to pierwsza migracja, wygenerowana klasa zawiera kod umożliwiający utworzenie schematu bazy danych. Schemat bazy danych jest oparty na modelu określonym wMvcMovieContext
klasie.
Zostanie wyświetlone następujące ostrzeżenie, które zostało rozwiązane w późniejszym kroku:
Nie określono typu magazynu dla właściwości dziesiętnej "Price" w typie jednostki "Movie". Spowoduje to dyskretne obcięcie wartości, jeśli nie mieszczą się w domyślnej precyzji i skali. Jawnie określ typ kolumny programu SQL Server, który może pomieścić wszystkie wartości w elemencie "OnModelCreating" przy użyciu polecenia "HasColumnType", określić precyzję i skalę przy użyciu polecenia "HasPrecision" lub skonfigurować konwerter wartości przy użyciu polecenia "HasConversion".
W usłudze PMC wprowadź następujące polecenie:
Update-Database
Update-Database
: aktualizuje bazę danych do najnowszej migracji, która została utworzona przez poprzednie polecenie. To polecenie uruchamia metodęUp
wMigrations/{time-stamp}_InitialCreate.cs
pliku, która tworzy bazę danych.
Aby uzyskać więcej informacji na temat narzędzi PMC dla EF Coreprogramu , zobacz EF Core dokumentacja narzędzi — PMC w programie Visual Studio.
Testowanie aplikacji
Uruchom aplikację i wybierz link Aplikacja filmowa.
Jeśli wystąpi wyjątek podobny do poniższego, być może pominięto Update-Database
polecenie w kroku migracji:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i w formatach dat innych niż angielskie stany USA, aplikacja musi zostać zglobalizowana. Aby uzyskać instrukcje dotyczące globalizacji, zobacz ten problem z usługą GitHub.
Sprawdzanie wygenerowanej klasy kontekstu bazy danych i rejestracji
W przypadku EF Coreprogramu dostęp do danych jest wykonywany przy użyciu modelu. Model składa się z klas jednostek i obiektu kontekstu, który reprezentuje sesję z bazą danych. Obiekt kontekstu umożliwia wykonywanie zapytań i zapisywanie danych. Kontekst bazy danych pochodzi z elementu Microsoft.EntityFrameworkCore.DbContext i określa jednostki do uwzględnienia w modelu danych.
Tworzenie szkieletu Data/MvcMovieContext.cs
powoduje utworzenie klasy kontekstu bazy danych:
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!;
}
}
Powyższy kod tworzy właściwość DbSet<Movie> reprezentującą filmy w bazie danych.
Wstrzykiwanie zależności
ASP.NET Core jest kompilowany przy użyciu wstrzykiwania zależności (DI). Usługi, takie jak kontekst bazy danych, są rejestrowane w usłudze DI w systemie Program.cs
. Te usługi są udostępniane składnikom, które wymagają ich za pośrednictwem parametrów konstruktora.
Controllers/MoviesController.cs
W pliku konstruktor używa wstrzykiwania zależności, aby wstrzyknąć MvcMovieContext
kontekst bazy danych do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Tworzenie szkieletu wygenerowało następujący wyróżniony kod w pliku 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.")));
System konfiguracji ASP.NET Core odczytuje bazę danych "MvcTextContext" parametry połączenia.
Badanie wygenerowanej bazy danych parametry połączenia
Tworzenie szkieletu dodało parametry połączenia do appsettings.json
pliku:
{
"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"
}
}
W przypadku programowania lokalnego system konfiguracji ASP.NET Core odczytuje ConnectionString
klucz z appsettings.json
pliku.
Klasa InitialCreate
Migrations/{timestamp}_InitialCreate.cs
Sprawdź plik migracji:
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");
}
}
}
Powyższy kod:
InitialCreate.Up
Tworzy tabelę Movie i konfigurujeId
jako klucz podstawowy.InitialCreate.Down
Przywraca zmiany schematu wprowadzone przez migracjęUp
.
Wstrzykiwanie zależności w kontrolerze
Controllers/MoviesController.cs
Otwórz plik i sprawdź konstruktor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Konstruktor używa wstrzykiwania zależności do wstrzykiwania kontekstu bazy danych (MvcMovieContext
) do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Przetestuj stronę Tworzenie . Wprowadź i prześlij dane.
Przetestuj strony Edytuj, Szczegóły i Usuń .
Silnie typizowane modele i @model
dyrektywa
Wcześniej w tym samouczku pokazano, jak kontroler może przekazywać dane lub obiekty do widoku przy użyciu słownika ViewData
. Słownik ViewData
jest obiektem dynamicznym, który zapewnia wygodny, opóźniony sposób przekazywania informacji do widoku.
MvC umożliwia przekazywanie silnie typiowanych obiektów modelu do widoku. To silnie typizowane podejście umożliwia sprawdzanie kodu czasu kompilacji. Mechanizm tworzenia szkieletów przekazał silnie typizowanego modelu w MoviesController
klasie i widokach.
Sprawdź wygenerowaną Details
metodę w Controllers/MoviesController.cs
pliku:
// 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);
}
Parametr id
jest zwykle przekazywany jako dane trasy. Na przykład https://localhost:5001/movies/details/1
zestawy:
- Kontroler kontrolera
movies
, pierwszy segment adresu URL. - Akcja na
details
, drugi segment adresu URL. - Od
id
1 do ostatniego segmentu adresu URL.
Element id
można przekazać za pomocą ciągu zapytania, jak w poniższym przykładzie:
https://localhost:5001/movies/details?id=1
Parametr id
jest definiowany jako typ dopuszczalny do wartości null (int?
) w przypadkach, gdy wartość nie jest podana id
.
Wyrażenie lambda jest przekazywane do FirstOrDefaultAsync metody , aby wybrać jednostki filmu zgodne z danymi trasy lub wartością ciągu zapytania.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Jeśli zostanie znaleziony film, wystąpienie Movie
modelu zostanie przekazane do Details
widoku:
return View(movie);
Sprawdź zawartość Views/Movies/Details.cshtml
pliku:
@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>
Instrukcja @model
w górnej części pliku widoku określa typ obiektu, którego oczekuje widok. Po utworzeniu kontrolera filmu dołączono następującą @model
instrukcję:
@model MvcMovie.Models.Movie
Ta @model
dyrektywa umożliwia dostęp do filmu przekazanego przez kontroler do widoku. Obiekt Model
jest silnie typizowane. Na przykład w Details.cshtml
widoku kod przekazuje każde pole filmu do DisplayNameFor
pomocników HTML z DisplayFor
silnie typiowanym Model
obiektem. Metody Create
i Edit
oraz widoki również przekazują Movie
obiekt modelu.
Sprawdź widok i metodę Index.cshtml
Index
w kontrolerze Filmy. Zwróć uwagę, że kod tworzy List
obiekt, gdy wywołuje metodę View
. Kod przekazuje tę Movies
listę z Index
metody akcji do widoku:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Kod zwraca szczegóły problemu, jeśli Movie
właściwość kontekstu danych ma wartość null.
Po utworzeniu kontrolera filmów szkielet zawiera następującą @model
instrukcję w górnej Index.cshtml
części pliku:
@model IEnumerable<MvcMovie.Models.Movie>
Dyrektywa @model
umożliwia dostęp do listy filmów przekazywanych przez kontroler do widoku przy użyciu silnie typizowanego Model
obiektu. Na przykład w Index.cshtml
widoku kod przechodzi przez filmy za pomocą foreach
instrukcji na silnie typizowanego Model
obiektu:
@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>
Model
Ponieważ obiekt jest silnie typowany jako IEnumerable<Movie>
obiekt, każdy element w pętli jest wpisywany jako Movie
. Między innymi kompilator weryfikuje typy używane w kodzie.
Dodatkowe zasoby
W tym samouczku klasy są dodawane do zarządzania filmami w bazie danych. Te klasy są częścią "odel" aplikacji MVC.
Te klasy modeli są używane z programem Entity Framework Core (EF Core) do pracy z bazą danych. EF Core to struktura mapowania relacyjnego (ORM, object-relational mapping), która upraszcza kod dostępu do danych, który trzeba napisać.
Utworzone klasy modeli są nazywane klasami POCO z Plain Old CLR Objects. Klasy POCO nie mają żadnej zależności od EF Coreklasy . Definiują tylko właściwości danych, które mają być przechowywane w bazie danych.
W tym samouczku klasy modeli są tworzone najpierw i EF Core tworzy bazę danych.
Dodawanie klasy modelu danych
Kliknij prawym przyciskiem myszy folder >Models Dodaj>klasę. Nazwij plik Movie.cs
.
Models/Movie.cs
Zaktualizuj plik przy użyciu następującego kodu:
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; }
}
Klasa Movie
zawiera Id
pole wymagane przez bazę danych dla klucza podstawowego.
Atrybut DataType on ReleaseDate
określa typ danych (Date
). Za pomocą tego atrybutu:
- Użytkownik nie musi wprowadzać informacji o godzinie w polu daty.
- Wyświetlana jest tylko data, a nie informacje o godzinie.
Adnotacje danych zostały omówione w późniejszym samouczku.
Znak zapytania po string
wskazuje, że właściwość jest dopuszczana do wartości null. Aby uzyskać więcej informacji, zobacz Typy referencyjne dopuszczane do wartości null.
Dodawanie pakietów NuGet
Program Visual Studio automatycznie instaluje wymagane pakiety.
Skompiluj projekt jako sprawdzenie błędów kompilatora.
Strony filmów szkieletowych
Narzędzie do tworzenia szkieletów umożliwia tworzenie Create
stron , Read
, Update
i Delete
(CRUD) dla modelu filmu.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Controllers i wybierz polecenie Dodaj > nowy element szkieletowy.
W oknie dialogowym Dodawanie nowego elementu szkieletu:
- W okienku po lewej stronie wybierz pozycję Zainstalowane>wspólne>MVC.
- Wybierz pozycję Kontroler MVC z widokami przy użyciu platformy Entity Framework.
- Wybierz Dodaj.
Ukończ okno dialogowe Dodawanie kontrolera MVC z widokami przy użyciu okna dialogowego Entity Framework:
- Z listy rozwijanej Klasa modelu wybierz pozycję Movie (MvcFilm.Models).
- W wierszu Klasy kontekstu danych wybierz + znak (plus).
- W oknie dialogowym Dodawanie kontekstu danych jest generowana nazwa klasy MvcFilm.Data.MvcTextContext.
- Wybierz Dodaj.
- Z listy rozwijanej Dostawca bazy danych wybierz pozycję SQL Server.
- Widoki i nazwa kontrolera: zachowaj wartość domyślną.
- Wybierz Dodaj.
Jeśli zostanie wyświetlony komunikat o błędzie, wybierz pozycję Dodaj po raz drugi, aby spróbować ponownie.
Tworzenie szkieletu dodaje następujące pakiety:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
Tworzenie szkieletu powoduje utworzenie następujących elementów:
- Kontroler filmów:
Controllers/MoviesController.cs
- Razor wyświetl pliki dla stron Tworzenie, Usuwanie, Szczegóły, Edytowanie i Indeks :
Views/Movies/*.cshtml
- Klasa kontekstu bazy danych:
Data/MvcMovieContext.cs
Tworzenie szkieletu aktualizuje następujące elementy:
- Wstawia wymagane odwołania do pakietu w
MvcMovie.csproj
pliku projektu. - Rejestruje kontekst bazy danych w
Program.cs
pliku. - Dodaje parametry połączenia bazy danych do
appsettings.json
pliku.
Automatyczne tworzenie tych plików i aktualizacji plików jest nazywane tworzeniem szkieletów.
Nie można jeszcze używać stron szkieletowych, ponieważ baza danych nie istnieje. Uruchomienie aplikacji i wybranie linku Aplikacja filmowa powoduje otwarcie bazy danych lub brak takiej tabeli: komunikat o błędzie Filmu .
Skompiluj aplikację, aby sprawdzić, czy nie ma żadnych błędów.
Migracja początkowa
EF CoreUżyj funkcji Migracje, aby utworzyć bazę danych. Migracje to zestaw narzędzi, które tworzą i aktualizują bazę danych w celu dopasowania ich do modelu danych.
Z menu Narzędzia wybierz pozycję NuGet Menedżer pakietów> Menedżer pakietów Konsola .
W konsoli Menedżer pakietów (PMC) wprowadź następujące polecenia:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: generujeMigrations/{timestamp}_InitialCreate.cs
plik migracji. ArgumentemInitialCreate
jest nazwa migracji. Można użyć dowolnej nazwy, ale zgodnie z konwencją wybrana jest nazwa opisującą migrację. Ponieważ jest to pierwsza migracja, wygenerowana klasa zawiera kod umożliwiający utworzenie schematu bazy danych. Schemat bazy danych jest oparty na modelu określonym wMvcMovieContext
klasie.Update-Database
: aktualizuje bazę danych do najnowszej migracji, która została utworzona przez poprzednie polecenie. To polecenie uruchamia metodęUp
wMigrations/{time-stamp}_InitialCreate.cs
pliku, która tworzy bazę danych.
Polecenie Update-Database
generuje następujące ostrzeżenie:
Nie określono typu magazynu dla właściwości dziesiętnej "Price" w typie jednostki "Movie". Spowoduje to dyskretne obcięcie wartości, jeśli nie mieszczą się w domyślnej precyzji i skali. Jawnie określ typ kolumny programu SQL Server, który może pomieścić wszystkie wartości w elemencie "OnModelCreating" przy użyciu polecenia "HasColumnType", określić precyzję i skalę przy użyciu polecenia "HasPrecision" lub skonfigurować konwerter wartości przy użyciu polecenia "HasConversion".
Zignoruj powyższe ostrzeżenie. Jest on naprawiony w późniejszym samouczku.
Aby uzyskać więcej informacji na temat narzędzi PMC dla EF Coreprogramu , zobacz EF Core dokumentacja narzędzi — PMC w programie Visual Studio.
Testowanie aplikacji
Uruchom aplikację i wybierz link Aplikacja filmowa.
Jeśli wystąpi wyjątek podobny do poniższego, być może pominięto Update-Database
polecenie w kroku migracji:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i w formatach dat innych niż angielskie stany USA, aplikacja musi zostać zglobalizowana. Aby uzyskać instrukcje dotyczące globalizacji, zobacz ten problem z usługą GitHub.
Sprawdzanie wygenerowanej klasy kontekstu bazy danych i rejestracji
W przypadku EF Coreprogramu dostęp do danych jest wykonywany przy użyciu modelu. Model składa się z klas jednostek i obiektu kontekstu, który reprezentuje sesję z bazą danych. Obiekt kontekstu umożliwia wykonywanie zapytań i zapisywanie danych. Kontekst bazy danych pochodzi z elementu Microsoft.EntityFrameworkCore.DbContext i określa jednostki do uwzględnienia w modelu danych.
Tworzenie szkieletu Data/MvcMovieContext.cs
powoduje utworzenie klasy kontekstu bazy danych:
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; }
}
}
Powyższy kod tworzy właściwość DbSet<Movie> reprezentującą filmy w bazie danych.
Wstrzykiwanie zależności
ASP.NET Core jest kompilowany przy użyciu wstrzykiwania zależności (DI). Usługi, takie jak kontekst bazy danych, są rejestrowane w usłudze DI w systemie Program.cs
. Te usługi są udostępniane składnikom, które wymagają ich za pośrednictwem parametrów konstruktora.
Controllers/MoviesController.cs
W pliku konstruktor używa wstrzykiwania zależności, aby wstrzyknąć MvcMovieContext
kontekst bazy danych do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Tworzenie szkieletu wygenerowało następujący wyróżniony kod w pliku Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
System konfiguracji ASP.NET Core odczytuje bazę danych "MvcTextContext" parametry połączenia.
Badanie wygenerowanej bazy danych parametry połączenia
Tworzenie szkieletu dodało parametry połączenia do appsettings.json
pliku:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Data Source=MvcMovieContext-ea7a4069-f366-4742-bd1c-3f753a804ce1.db"
}
}
W przypadku programowania lokalnego system konfiguracji ASP.NET Core odczytuje ConnectionString
klucz z appsettings.json
pliku.
Klasa InitialCreate
Migrations/{timestamp}_InitialCreate.cs
Sprawdź plik migracji:
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");
}
}
}
Powyższy kod:
InitialCreate.Up
Tworzy tabelę Movie i konfigurujeId
jako klucz podstawowy.InitialCreate.Down
Przywraca zmiany schematu wprowadzone przez migracjęUp
.
Wstrzykiwanie zależności w kontrolerze
Controllers/MoviesController.cs
Otwórz plik i sprawdź konstruktor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Konstruktor używa wstrzykiwania zależności do wstrzykiwania kontekstu bazy danych (MvcMovieContext
) do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Przetestuj stronę Tworzenie . Wprowadź i prześlij dane.
Przetestuj strony Edytuj, Szczegóły i Usuń .
Silnie typizowane modele i @model
dyrektywa
Wcześniej w tym samouczku pokazano, jak kontroler może przekazywać dane lub obiekty do widoku przy użyciu słownika ViewData
. Słownik ViewData
jest obiektem dynamicznym, który zapewnia wygodny, opóźniony sposób przekazywania informacji do widoku.
MvC umożliwia przekazywanie silnie typiowanych obiektów modelu do widoku. To silnie typizowane podejście umożliwia sprawdzanie kodu czasu kompilacji. Mechanizm tworzenia szkieletów przekazał silnie typizowanego modelu w MoviesController
klasie i widokach.
Sprawdź wygenerowaną Details
metodę w Controllers/MoviesController.cs
pliku:
// 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);
}
Parametr id
jest zwykle przekazywany jako dane trasy. Na przykład https://localhost:5001/movies/details/1
zestawy:
- Kontroler kontrolera
movies
, pierwszy segment adresu URL. - Akcja na
details
, drugi segment adresu URL. - Od
id
1 do ostatniego segmentu adresu URL.
Element id
można przekazać za pomocą ciągu zapytania, jak w poniższym przykładzie:
https://localhost:5001/movies/details?id=1
Parametr id
jest definiowany jako typ dopuszczalny do wartości null (int?
) w przypadkach, gdy wartość nie jest podana id
.
Wyrażenie lambda jest przekazywane do FirstOrDefaultAsync metody , aby wybrać jednostki filmu zgodne z danymi trasy lub wartością ciągu zapytania.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Jeśli zostanie znaleziony film, wystąpienie Movie
modelu zostanie przekazane do Details
widoku:
return View(movie);
Sprawdź zawartość Views/Movies/Details.cshtml
pliku:
@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>
Instrukcja @model
w górnej części pliku widoku określa typ obiektu, którego oczekuje widok. Po utworzeniu kontrolera filmu dołączono następującą @model
instrukcję:
@model MvcMovie.Models.Movie
Ta @model
dyrektywa umożliwia dostęp do filmu przekazanego przez kontroler do widoku. Obiekt Model
jest silnie typizowane. Na przykład w Details.cshtml
widoku kod przekazuje każde pole filmu do DisplayNameFor
pomocników HTML z DisplayFor
silnie typiowanym Model
obiektem. Metody Create
i Edit
oraz widoki również przekazują Movie
obiekt modelu.
Sprawdź widok i metodę Index.cshtml
Index
w kontrolerze Filmy. Zwróć uwagę, że kod tworzy List
obiekt, gdy wywołuje metodę View
. Kod przekazuje tę Movies
listę z Index
metody akcji do widoku:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Kod zwraca szczegóły problemu, jeśli Movie
właściwość kontekstu danych ma wartość null.
Po utworzeniu kontrolera filmów szkielet zawiera następującą @model
instrukcję w górnej Index.cshtml
części pliku:
@model IEnumerable<MvcMovie.Models.Movie>
Dyrektywa @model
umożliwia dostęp do listy filmów przekazywanych przez kontroler do widoku przy użyciu silnie typizowanego Model
obiektu. Na przykład w Index.cshtml
widoku kod przechodzi przez filmy za pomocą foreach
instrukcji na silnie typizowanego Model
obiektu:
@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>
Model
Ponieważ obiekt jest silnie typowany jako IEnumerable<Movie>
obiekt, każdy element w pętli jest wpisywany jako Movie
. Między innymi kompilator weryfikuje typy używane w kodzie.
Dodatkowe zasoby
W tym samouczku klasy są dodawane do zarządzania filmami w bazie danych. Te klasy są częścią "odel" aplikacji MVC.
Te klasy modeli są używane z programem Entity Framework Core (EF Core) do pracy z bazą danych. EF Core to struktura mapowania relacyjnego (ORM, object-relational mapping), która upraszcza kod dostępu do danych, który trzeba napisać.
Utworzone klasy modeli są nazywane klasami POCO z Plain Old CLR Objects. Klasy POCO nie mają żadnej zależności od EF Coreklasy . Definiują tylko właściwości danych, które mają być przechowywane w bazie danych.
W tym samouczku klasy modeli są tworzone najpierw i EF Core tworzy bazę danych.
Dodawanie klasy modelu danych
Kliknij prawym przyciskiem myszy folder >Models Dodaj>klasę. Nazwij plik Movie.cs
.
Models/Movie.cs
Zaktualizuj plik przy użyciu następującego kodu:
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; }
}
Klasa Movie
zawiera Id
pole wymagane przez bazę danych dla klucza podstawowego.
Atrybut DataType on ReleaseDate
określa typ danych (Date
). Za pomocą tego atrybutu:
- Użytkownik nie musi wprowadzać informacji o godzinie w polu daty.
- Wyświetlana jest tylko data, a nie informacje o godzinie.
Adnotacje danych zostały omówione w późniejszym samouczku.
Znak zapytania po string
wskazuje, że właściwość jest dopuszczana do wartości null. Aby uzyskać więcej informacji, zobacz Typy referencyjne dopuszczane do wartości null.
Dodawanie pakietów NuGet
Program Visual Studio automatycznie instaluje wymagane pakiety.
Skompiluj projekt jako sprawdzenie błędów kompilatora.
Strony filmów szkieletowych
Narzędzie do tworzenia szkieletów umożliwia tworzenie Create
stron , Read
, Update
i Delete
(CRUD) dla modelu filmu.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Controllers i wybierz polecenie Dodaj > nowy element szkieletowy.
W oknie dialogowym Dodawanie nowego elementu szkieletu:
- W okienku po lewej stronie wybierz pozycję Zainstalowane>wspólne>MVC.
- Wybierz pozycję Kontroler MVC z widokami przy użyciu platformy Entity Framework.
- Wybierz Dodaj.
Ukończ okno dialogowe Dodawanie kontrolera MVC z widokami przy użyciu okna dialogowego Entity Framework:
- Z listy rozwijanej Klasa modelu wybierz pozycję Movie (MvcFilm.Models).
- W wierszu Klasy kontekstu danych wybierz + znak (plus).
- W oknie dialogowym Dodawanie kontekstu danych jest generowana nazwa klasy MvcFilm.Data.MvcTextContext.
- Wybierz Dodaj.
- Z listy rozwijanej Dostawca bazy danych wybierz pozycję SQL Server.
- Widoki i nazwa kontrolera: zachowaj wartość domyślną.
- Wybierz Dodaj.
Jeśli zostanie wyświetlony komunikat o błędzie, wybierz pozycję Dodaj po raz drugi, aby spróbować ponownie.
Tworzenie szkieletu dodaje następujące pakiety:
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
Tworzenie szkieletu powoduje utworzenie następujących elementów:
- Kontroler filmów:
Controllers/MoviesController.cs
- Razor wyświetl pliki dla stron Tworzenie, Usuwanie, Szczegóły, Edytowanie i Indeks :
Views/Movies/*.cshtml
- Klasa kontekstu bazy danych:
Data/MvcMovieContext.cs
Tworzenie szkieletu aktualizuje następujące elementy:
- Wstawia wymagane odwołania do pakietu w
MvcMovie.csproj
pliku projektu. - Rejestruje kontekst bazy danych w
Program.cs
pliku. - Dodaje parametry połączenia bazy danych do
appsettings.json
pliku.
Automatyczne tworzenie tych plików i aktualizacji plików jest nazywane tworzeniem szkieletów.
Nie można jeszcze używać stron szkieletowych, ponieważ baza danych nie istnieje. Uruchomienie aplikacji i wybranie linku Aplikacja filmowa powoduje otwarcie bazy danych lub brak takiej tabeli: komunikat o błędzie Filmu .
Skompiluj aplikację, aby sprawdzić, czy nie ma żadnych błędów.
Migracja początkowa
EF CoreUżyj funkcji Migracje, aby utworzyć bazę danych. Migracje to zestaw narzędzi, które tworzą i aktualizują bazę danych w celu dopasowania ich do modelu danych.
Z menu Narzędzia wybierz pozycję NuGet Menedżer pakietów> Menedżer pakietów Konsola .
W konsoli Menedżer pakietów (PMC) wprowadź następujące polecenia:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: generujeMigrations/{timestamp}_InitialCreate.cs
plik migracji. ArgumentemInitialCreate
jest nazwa migracji. Można użyć dowolnej nazwy, ale zgodnie z konwencją wybrana jest nazwa opisującą migrację. Ponieważ jest to pierwsza migracja, wygenerowana klasa zawiera kod umożliwiający utworzenie schematu bazy danych. Schemat bazy danych jest oparty na modelu określonym wMvcMovieContext
klasie.Update-Database
: aktualizuje bazę danych do najnowszej migracji, która została utworzona przez poprzednie polecenie. To polecenie uruchamia metodęUp
wMigrations/{time-stamp}_InitialCreate.cs
pliku, która tworzy bazę danych.
Polecenie Update-Database
generuje następujące ostrzeżenie:
Nie określono typu dla kolumny dziesiętnej "Price" w typie jednostki "Movie". Spowoduje to dyskretne obcięcie wartości, jeśli nie mieszczą się w domyślnej precyzji i skali. Jawnie określ typ kolumny serwera SQL, który może pomieścić wszystkie wartości przy użyciu polecenia "HasColumnType()".
Zignoruj powyższe ostrzeżenie. Jest on naprawiony w późniejszym samouczku.
Aby uzyskać więcej informacji na temat narzędzi PMC dla EF Coreprogramu , zobacz EF Core dokumentacja narzędzi — PMC w programie Visual Studio.
Testowanie aplikacji
Uruchom aplikację i wybierz link Aplikacja filmowa.
Jeśli wystąpi wyjątek podobny do poniższego, być może pominięto Update-Database
polecenie w kroku migracji:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i w formatach dat innych niż angielskie stany USA, aplikacja musi zostać zglobalizowana. Aby uzyskać instrukcje dotyczące globalizacji, zobacz ten problem z usługą GitHub.
Sprawdzanie wygenerowanej klasy kontekstu bazy danych i rejestracji
W przypadku EF Coreprogramu dostęp do danych jest wykonywany przy użyciu modelu. Model składa się z klas jednostek i obiektu kontekstu, który reprezentuje sesję z bazą danych. Obiekt kontekstu umożliwia wykonywanie zapytań i zapisywanie danych. Kontekst bazy danych pochodzi z elementu Microsoft.EntityFrameworkCore.DbContext i określa jednostki do uwzględnienia w modelu danych.
Tworzenie szkieletu Data/MvcMovieContext.cs
powoduje utworzenie klasy kontekstu bazy danych:
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; }
}
}
Powyższy kod tworzy właściwość DbSet<Movie> reprezentującą filmy w bazie danych.
Wstrzykiwanie zależności
ASP.NET Core jest kompilowany przy użyciu wstrzykiwania zależności (DI). Usługi, takie jak kontekst bazy danych, są rejestrowane w usłudze DI w systemie Program.cs
. Te usługi są udostępniane składnikom, które wymagają ich za pośrednictwem parametrów konstruktora.
Controllers/MoviesController.cs
W pliku konstruktor używa wstrzykiwania zależności, aby wstrzyknąć MvcMovieContext
kontekst bazy danych do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Tworzenie szkieletu wygenerowało następujący wyróżniony kod w pliku Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
System konfiguracji ASP.NET Core odczytuje bazę danych "MvcTextContext" parametry połączenia.
Badanie wygenerowanej bazy danych parametry połączenia
Tworzenie szkieletu dodało parametry połączenia do appsettings.json
pliku:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Data Source=MvcMovieContext-ea7a4069-f366-4742-bd1c-3f753a804ce1.db"
}
}
W przypadku programowania lokalnego system konfiguracji ASP.NET Core odczytuje ConnectionString
klucz z appsettings.json
pliku.
Klasa InitialCreate
Migrations/{timestamp}_InitialCreate.cs
Sprawdź plik migracji:
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");
}
}
}
Powyższy kod:
InitialCreate.Up
Tworzy tabelę Movie i konfigurujeId
jako klucz podstawowy.InitialCreate.Down
Przywraca zmiany schematu wprowadzone przez migracjęUp
.
Wstrzykiwanie zależności w kontrolerze
Controllers/MoviesController.cs
Otwórz plik i sprawdź konstruktor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Konstruktor używa wstrzykiwania zależności do wstrzykiwania kontekstu bazy danych (MvcMovieContext
) do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Przetestuj stronę Tworzenie . Wprowadź i prześlij dane.
Przetestuj strony Edytuj, Szczegóły i Usuń .
Silnie typizowane modele i @model
dyrektywa
Wcześniej w tym samouczku pokazano, jak kontroler może przekazywać dane lub obiekty do widoku przy użyciu słownika ViewData
. Słownik ViewData
jest obiektem dynamicznym, który zapewnia wygodny, opóźniony sposób przekazywania informacji do widoku.
MvC umożliwia przekazywanie silnie typiowanych obiektów modelu do widoku. To silnie typizowane podejście umożliwia sprawdzanie kodu czasu kompilacji. Mechanizm tworzenia szkieletów przekazał silnie typizowanego modelu w MoviesController
klasie i widokach.
Sprawdź wygenerowaną Details
metodę w Controllers/MoviesController.cs
pliku:
// 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);
}
Parametr id
jest zwykle przekazywany jako dane trasy. Na przykład https://localhost:5001/movies/details/1
zestawy:
- Kontroler kontrolera
movies
, pierwszy segment adresu URL. - Akcja na
details
, drugi segment adresu URL. - Od
id
1 do ostatniego segmentu adresu URL.
Element id
można przekazać za pomocą ciągu zapytania, jak w poniższym przykładzie:
https://localhost:5001/movies/details?id=1
Parametr id
jest definiowany jako typ dopuszczalny do wartości null (int?
) w przypadkach, gdy wartość nie jest podana id
.
Wyrażenie lambda jest przekazywane do FirstOrDefaultAsync metody , aby wybrać jednostki filmu zgodne z danymi trasy lub wartością ciągu zapytania.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Jeśli zostanie znaleziony film, wystąpienie Movie
modelu zostanie przekazane do Details
widoku:
return View(movie);
Sprawdź zawartość Views/Movies/Details.cshtml
pliku:
@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>
Instrukcja @model
w górnej części pliku widoku określa typ obiektu, którego oczekuje widok. Po utworzeniu kontrolera filmu dołączono następującą @model
instrukcję:
@model MvcMovie.Models.Movie
Ta @model
dyrektywa umożliwia dostęp do filmu przekazanego przez kontroler do widoku. Obiekt Model
jest silnie typizowane. Na przykład w Details.cshtml
widoku kod przekazuje każde pole filmu do DisplayNameFor
pomocników HTML z DisplayFor
silnie typiowanym Model
obiektem. Metody Create
i Edit
oraz widoki również przekazują Movie
obiekt modelu.
Sprawdź widok i metodę Index.cshtml
Index
w kontrolerze Filmy. Zwróć uwagę, że kod tworzy List
obiekt, gdy wywołuje metodę View
. Kod przekazuje tę Movies
listę z Index
metody akcji do widoku:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Kod zwraca szczegóły problemu, jeśli Movie
właściwość kontekstu danych ma wartość null.
Po utworzeniu kontrolera filmów szkielet zawiera następującą @model
instrukcję w górnej Index.cshtml
części pliku:
@model IEnumerable<MvcMovie.Models.Movie>
Dyrektywa @model
umożliwia dostęp do listy filmów przekazywanych przez kontroler do widoku przy użyciu silnie typizowanego Model
obiektu. Na przykład w Index.cshtml
widoku kod przechodzi przez filmy za pomocą foreach
instrukcji na silnie typizowanego Model
obiektu:
@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>
Model
Ponieważ obiekt jest silnie typowany jako IEnumerable<Movie>
obiekt, każdy element w pętli jest wpisywany jako Movie
. Między innymi kompilator weryfikuje typy używane w kodzie.
Dodatkowe zasoby
W tym samouczku klasy są dodawane do zarządzania filmami w bazie danych. Te klasy są częścią "odel" aplikacji MVC.
Te klasy modeli są używane z programem Entity Framework Core (EF Core) do pracy z bazą danych. EF Core to struktura mapowania relacyjnego (ORM, object-relational mapping), która upraszcza kod dostępu do danych, który trzeba napisać.
Utworzone klasy modeli są nazywane klasami POCO z Plain Old CLR Objects. Klasy POCO nie mają żadnej zależności od EF Coreklasy . Definiują tylko właściwości danych, które mają być przechowywane w bazie danych.
W tym samouczku klasy modeli są tworzone najpierw i EF Core tworzy bazę danych.
Dodawanie klasy modelu danych
Kliknij prawym przyciskiem myszy folder >Models Dodaj>klasę. Nazwij plik Movie.cs
.
Models/Movie.cs
Zaktualizuj plik przy użyciu następującego kodu:
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; }
}
}
Klasa Movie
zawiera Id
pole wymagane przez bazę danych dla klucza podstawowego.
Atrybut DataType on ReleaseDate
określa typ danych (Date
). Za pomocą tego atrybutu:
- Użytkownik nie musi wprowadzać informacji o godzinie w polu daty.
- Wyświetlana jest tylko data, a nie informacje o godzinie.
Adnotacje danych zostały omówione w późniejszym samouczku.
Znak zapytania po string
wskazuje, że właściwość jest dopuszczana do wartości null. Aby uzyskać więcej informacji, zobacz Typy referencyjne dopuszczane do wartości null.
Dodawanie pakietów NuGet
Z menu Narzędzia wybierz pozycję NuGet Menedżer pakietów> Menedżer pakietów Konsola (PMC).
W usłudze PMC uruchom następujące polecenie:
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Powyższe polecenia dodają:
- EF Core Dostawca programu SQL Server. Pakiet dostawcy EF Core instaluje pakiet jako zależność.
- Narzędzia używane przez pakiety zainstalowane automatycznie w kroku tworzenia szkieletu w dalszej części tego samouczka.
Skompiluj projekt jako sprawdzenie błędów kompilatora.
Strony filmów szkieletowych
Narzędzie do tworzenia szkieletów umożliwia tworzenie Create
stron , Read
, Update
i Delete
(CRUD) dla modelu filmu.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Controllers i wybierz polecenie Dodaj > nowy element szkieletowy.
W oknie dialogowym Dodawanie szkieletu wybierz pozycję Kontroler MVC z widokami, używając polecenia Entity Framework > Add.
Ukończ okno dialogowe Dodawanie kontrolera MVC z widokami przy użyciu okna dialogowego Entity Framework:
- Z listy rozwijanej Klasa modelu wybierz pozycję Movie (MvcFilm.Models).
- W wierszu Klasy kontekstu danych wybierz + znak (plus).
- W oknie dialogowym Dodawanie kontekstu danych jest generowana nazwa klasy MvcFilm.Data.MvcTextContext.
- Wybierz Dodaj.
- Widoki i nazwa kontrolera: zachowaj wartość domyślną.
- Wybierz Dodaj.
Jeśli zostanie wyświetlony komunikat o błędzie, wybierz pozycję Dodaj po raz drugi, aby spróbować ponownie.
Tworzenie szkieletu aktualizuje następujące elementy:
- Wstawia wymagane odwołania do pakietu w
MvcMovie.csproj
pliku projektu. - Rejestruje kontekst bazy danych w
Program.cs
pliku. - Dodaje parametry połączenia bazy danych do
appsettings.json
pliku.
Tworzenie szkieletu powoduje utworzenie następujących elementów:
- Kontroler filmów:
Controllers/MoviesController.cs
- Razor wyświetl pliki dla stron Tworzenie, Usuwanie, Szczegóły, Edytowanie i Indeks :
Views/Movies/*.cshtml
- Klasa kontekstu bazy danych:
Data/MvcMovieContext.cs
Automatyczne tworzenie tych plików i aktualizacji plików jest nazywane tworzeniem szkieletów.
Nie można jeszcze używać stron szkieletowych, ponieważ baza danych nie istnieje. Uruchomienie aplikacji i wybranie linku Aplikacja filmowa powoduje otwarcie bazy danych lub brak takiej tabeli: komunikat o błędzie Filmu .
Tworzenie aplikacji
Kompilowanie aplikacji. Kompilator generuje kilka ostrzeżeń dotyczących sposobu null
obsługi wartości. Aby uzyskać więcej informacji, zobacz ten problem z usługą GitHub i typy referencyjne dopuszczane do wartości null.
Aby wyeliminować ostrzeżenia z typów odwołań dopuszczanych do wartości null, usuń następujący wiersz z MvcMovie.csproj
pliku:
<Nullable>enable</Nullable>
Mamy nadzieję rozwiązać ten problem w następnej wersji.
Migracja początkowa
EF CoreUżyj funkcji Migracje, aby utworzyć bazę danych. Migracje to zestaw narzędzi, które tworzą i aktualizują bazę danych w celu dopasowania ich do modelu danych.
Z menu Narzędzia wybierz pozycję NuGet Menedżer pakietów> Menedżer pakietów Konsola .
W konsoli Menedżer pakietów (PMC) wprowadź następujące polecenia:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: generujeMigrations/{timestamp}_InitialCreate.cs
plik migracji. ArgumentemInitialCreate
jest nazwa migracji. Można użyć dowolnej nazwy, ale zgodnie z konwencją wybrana jest nazwa opisującą migrację. Ponieważ jest to pierwsza migracja, wygenerowana klasa zawiera kod umożliwiający utworzenie schematu bazy danych. Schemat bazy danych jest oparty na modelu określonym wMvcMovieContext
klasie.Update-Database
: aktualizuje bazę danych do najnowszej migracji, która została utworzona przez poprzednie polecenie. To polecenie uruchamia metodęUp
wMigrations/{time-stamp}_InitialCreate.cs
pliku, która tworzy bazę danych.
Polecenie Update-Database
generuje następujące ostrzeżenie:
Nie określono typu dla kolumny dziesiętnej "Price" w typie jednostki "Movie". Spowoduje to dyskretne obcięcie wartości, jeśli nie mieszczą się w domyślnej precyzji i skali. Jawnie określ typ kolumny serwera SQL, który może pomieścić wszystkie wartości przy użyciu polecenia "HasColumnType()".
Zignoruj powyższe ostrzeżenie. Jest on naprawiony w późniejszym samouczku.
Aby uzyskać więcej informacji na temat narzędzi PMC dla EF Coreprogramu , zobacz EF Core dokumentacja narzędzi — PMC w programie Visual Studio.
Testowanie aplikacji
Uruchom aplikację i wybierz link Aplikacja filmowa.
Jeśli wystąpi wyjątek podobny do poniższego, być może pominięto krok migracji:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i w formatach dat innych niż angielskie stany USA, aplikacja musi zostać zglobalizowana. Aby uzyskać instrukcje dotyczące globalizacji, zobacz ten problem z usługą GitHub.
Sprawdzanie wygenerowanej klasy kontekstu bazy danych i rejestracji
W przypadku EF Coreprogramu dostęp do danych jest wykonywany przy użyciu modelu. Model składa się z klas jednostek i obiektu kontekstu, który reprezentuje sesję z bazą danych. Obiekt kontekstu umożliwia wykonywanie zapytań i zapisywanie danych. Kontekst bazy danych pochodzi z elementu Microsoft.EntityFrameworkCore.DbContext i określa jednostki do uwzględnienia w modelu danych.
Tworzenie szkieletu Data/MvcMovieContext.cs
powoduje utworzenie klasy kontekstu bazy danych:
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; }
}
}
Powyższy kod tworzy właściwość DbSet<Movie> reprezentującą filmy w bazie danych.
Wstrzykiwanie zależności
ASP.NET Core jest kompilowany przy użyciu wstrzykiwania zależności (DI). Usługi, takie jak kontekst bazy danych, są rejestrowane w usłudze DI w systemie Program.cs
. Te usługi są udostępniane składnikom, które wymagają ich za pośrednictwem parametrów konstruktora.
Controllers/MoviesController.cs
W pliku konstruktor używa wstrzykiwania zależności, aby wstrzyknąć MvcMovieContext
kontekst bazy danych do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Tworzenie szkieletu wygenerowało następujący wyróżniony kod w pliku Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
System konfiguracji ASP.NET Core odczytuje bazę danych "MvcTextContext" parametry połączenia.
Badanie wygenerowanej bazy danych parametry połączenia
Tworzenie szkieletu dodało parametry połączenia do appsettings.json
pliku:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-7dc5;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
W przypadku programowania lokalnego system konfiguracji ASP.NET Core odczytuje ConnectionString
klucz z appsettings.json
pliku.
Klasa InitialCreate
Migrations/{timestamp}_InitialCreate.cs
Sprawdź plik migracji:
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");
}
}
}
Powyższy kod:
InitialCreate.Up
Tworzy tabelę Movie i konfigurujeId
jako klucz podstawowy.InitialCreate.Down
Przywraca zmiany schematu wprowadzone przez migracjęUp
.
Wstrzykiwanie zależności w kontrolerze
Controllers/MoviesController.cs
Otwórz plik i sprawdź konstruktor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Konstruktor używa wstrzykiwania zależności do wstrzykiwania kontekstu bazy danych (MvcMovieContext
) do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Przetestuj stronę Tworzenie . Wprowadź i prześlij dane.
Przetestuj strony Edytuj, Szczegóły i Usuń .
Silnie typizowane modele i @model
dyrektywa
Wcześniej w tym samouczku pokazano, jak kontroler może przekazywać dane lub obiekty do widoku przy użyciu słownika ViewData
. Słownik ViewData
jest obiektem dynamicznym, który zapewnia wygodny, opóźniony sposób przekazywania informacji do widoku.
MvC umożliwia przekazywanie silnie typiowanych obiektów modelu do widoku. To silnie typizowane podejście umożliwia sprawdzanie kodu czasu kompilacji. Mechanizm tworzenia szkieletów przekazał silnie typizowanego modelu w MoviesController
klasie i widokach.
Sprawdź wygenerowaną Details
metodę w Controllers/MoviesController.cs
pliku:
// 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);
}
Parametr id
jest zwykle przekazywany jako dane trasy. Na przykład https://localhost:5001/movies/details/1
zestawy:
- Kontroler kontrolera
movies
, pierwszy segment adresu URL. - Akcja na
details
, drugi segment adresu URL. - Od
id
1 do ostatniego segmentu adresu URL.
Element id
można przekazać za pomocą ciągu zapytania, jak w poniższym przykładzie:
https://localhost:5001/movies/details?id=1
Parametr id
jest definiowany jako typ dopuszczalny do wartości null (int?
) w przypadkach, gdy wartość nie jest podana id
.
Wyrażenie lambda jest przekazywane do FirstOrDefaultAsync metody , aby wybrać jednostki filmu zgodne z danymi trasy lub wartością ciągu zapytania.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Jeśli zostanie znaleziony film, wystąpienie Movie
modelu zostanie przekazane do Details
widoku:
return View(movie);
Sprawdź zawartość Views/Movies/Details.cshtml
pliku:
@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>
Instrukcja @model
w górnej części pliku widoku określa typ obiektu, którego oczekuje widok. Po utworzeniu kontrolera filmu dołączono następującą @model
instrukcję:
@model MvcMovie.Models.Movie
Ta @model
dyrektywa umożliwia dostęp do filmu przekazanego przez kontroler do widoku. Obiekt Model
jest silnie typizowane. Na przykład w Details.cshtml
widoku kod przekazuje każde pole filmu do DisplayNameFor
pomocników HTML z DisplayFor
silnie typiowanym Model
obiektem. Metody Create
i Edit
oraz widoki również przekazują Movie
obiekt modelu.
Sprawdź widok i metodę Index.cshtml
Index
w kontrolerze Filmy. Zwróć uwagę, że kod tworzy List
obiekt, gdy wywołuje metodę View
. Kod przekazuje tę Movies
listę z Index
metody akcji do widoku:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Po utworzeniu kontrolera filmów szkielet zawiera następującą @model
instrukcję w górnej Index.cshtml
części pliku:
@model IEnumerable<MvcMovie.Models.Movie>
Dyrektywa @model
umożliwia dostęp do listy filmów przekazywanych przez kontroler do widoku przy użyciu silnie typizowanego Model
obiektu. Na przykład w Index.cshtml
widoku kod przechodzi przez filmy za pomocą foreach
instrukcji na silnie typizowanego Model
obiektu:
@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>
Model
Ponieważ obiekt jest silnie typowany jako IEnumerable<Movie>
obiekt, każdy element w pętli jest wpisywany jako Movie
. Między innymi kompilator weryfikuje typy używane w kodzie.
Dodatkowe zasoby
W tym samouczku klasy są dodawane do zarządzania filmami w bazie danych. Te klasy są częścią "odel" aplikacji MVC.
Te klasy modeli są używane z programem Entity Framework Core (EF Core) do pracy z bazą danych. EF Core to struktura mapowania relacyjnego (ORM, object-relational mapping), która upraszcza kod dostępu do danych, który trzeba napisać.
Utworzone klasy modeli są nazywane klasami POCO z Plain Old CLR Objects. Klasy POCO nie mają żadnej zależności od EF Coreklasy . Definiują tylko właściwości danych, które mają być przechowywane w bazie danych.
W tym samouczku klasy modeli są tworzone najpierw i EF Core tworzy bazę danych.
Dodawanie klasy modelu danych
Kliknij prawym przyciskiem myszy folder >Models Dodaj>klasę. Nazwij plik Movie.cs
.
Models/Movie.cs
Zaktualizuj plik przy użyciu następującego kodu:
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; }
}
}
Klasa Movie
zawiera Id
pole wymagane przez bazę danych dla klucza podstawowego.
Atrybut DataType on ReleaseDate
określa typ danych (Date
). Za pomocą tego atrybutu:
- Użytkownik nie musi wprowadzać informacji o godzinie w polu daty.
- Wyświetlana jest tylko data, a nie informacje o godzinie.
Adnotacje danych zostały omówione w późniejszym samouczku.
Dodawanie pakietów NuGet
Z menu Narzędzia wybierz pozycję NuGet Menedżer pakietów> Menedżer pakietów Konsola (PMC).
W usłudze PMC uruchom następujące polecenie:
Install-Package Microsoft.EntityFrameworkCore.Design
Powyższe polecenia dodają:
- EF Core Dostawca programu SQL Server. Pakiet dostawcy EF Core instaluje pakiet jako zależność.
- Narzędzia używane przez pakiety zainstalowane automatycznie w kroku tworzenia szkieletu w dalszej części tego samouczka.
Skompiluj projekt jako sprawdzenie błędów kompilatora.
Strony filmów szkieletowych
Narzędzie do tworzenia szkieletów umożliwia tworzenie Create
stron , Read
, Update
i Delete
(CRUD) dla modelu filmu.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Controllers i wybierz polecenie Dodaj > nowy element szkieletowy.
W oknie dialogowym Dodawanie szkieletu wybierz pozycję Kontroler MVC z widokami, używając polecenia Entity Framework > Add.
Ukończ okno dialogowe Dodawanie kontrolera MVC z widokami przy użyciu okna dialogowego Entity Framework:
- Z listy rozwijanej Klasa modelu wybierz pozycję Movie (MvcFilm.Models).
- W wierszu Klasy kontekstu danych wybierz + znak (plus).
- W oknie dialogowym Dodawanie kontekstu danych jest generowana nazwa klasy MvcFilm.Data.MvcTextContext.
- Wybierz Dodaj.
- Widoki i nazwa kontrolera: zachowaj wartość domyślną.
- Wybierz Dodaj.
Tworzenie szkieletu aktualizuje następujące elementy:
- Wstawia wymagane odwołania do pakietu w
MvcMovie.csproj
pliku projektu. - Rejestruje kontekst bazy danych w
Startup.ConfigureServices
Startup.cs
pliku. - Dodaje parametry połączenia bazy danych do
appsettings.json
pliku.
Tworzenie szkieletu powoduje utworzenie następujących elementów:
- Kontroler filmów:
Controllers/MoviesController.cs
- Razor wyświetl pliki dla stron Tworzenie, Usuwanie, Szczegóły, Edytowanie i Indeks :
Views/Movies/*.cshtml
- Klasa kontekstu bazy danych:
Data/MvcMovieContext.cs
Automatyczne tworzenie tych plików i aktualizacji plików jest nazywane tworzeniem szkieletów.
Nie można jeszcze używać stron szkieletowych, ponieważ baza danych nie istnieje. Uruchomienie aplikacji i wybranie linku Aplikacja filmowa powoduje otwarcie bazy danych lub brak takiej tabeli: komunikat o błędzie Filmu .
Migracja początkowa
EF CoreUżyj funkcji Migracje, aby utworzyć bazę danych. Migracje to zestaw narzędzi, które tworzą i aktualizują bazę danych w celu dopasowania ich do modelu danych.
Z menu Narzędzia wybierz pozycję NuGet Menedżer pakietów> Menedżer pakietów Konsola .
W konsoli Menedżer pakietów (PMC) wprowadź następujące polecenia:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: generujeMigrations/{timestamp}_InitialCreate.cs
plik migracji. ArgumentemInitialCreate
jest nazwa migracji. Można użyć dowolnej nazwy, ale zgodnie z konwencją wybrana jest nazwa opisującą migrację. Ponieważ jest to pierwsza migracja, wygenerowana klasa zawiera kod umożliwiający utworzenie schematu bazy danych. Schemat bazy danych jest oparty na modelu określonym wMvcMovieContext
klasie.Update-Database
: aktualizuje bazę danych do najnowszej migracji, która została utworzona przez poprzednie polecenie. To polecenie uruchamia metodęUp
wMigrations/{time-stamp}_InitialCreate.cs
pliku, która tworzy bazę danych.
Polecenie Update-Database
generuje następujące ostrzeżenie:
Nie określono typu dla kolumny dziesiętnej "Price" w typie jednostki "Movie". Spowoduje to dyskretne obcięcie wartości, jeśli nie mieszczą się w domyślnej precyzji i skali. Jawnie określ typ kolumny serwera SQL, który może pomieścić wszystkie wartości przy użyciu polecenia "HasColumnType()".
Zignoruj powyższe ostrzeżenie. Jest on naprawiony w późniejszym samouczku.
Aby uzyskać więcej informacji na temat narzędzi PMC dla EF Coreprogramu , zobacz EF Core dokumentacja narzędzi — PMC w programie Visual Studio.
Testowanie aplikacji
Uruchom aplikację i wybierz link Aplikacja filmowa.
Jeśli wystąpi wyjątek podobny do poniższego, być może pominięto krok migracji:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i w formatach dat innych niż angielskie stany USA, aplikacja musi zostać zglobalizowana. Aby uzyskać instrukcje dotyczące globalizacji, zobacz ten problem z usługą GitHub.
Sprawdzanie wygenerowanej klasy kontekstu bazy danych i rejestracji
W przypadku EF Coreprogramu dostęp do danych jest wykonywany przy użyciu modelu. Model składa się z klas jednostek i obiektu kontekstu, który reprezentuje sesję z bazą danych. Obiekt kontekstu umożliwia wykonywanie zapytań i zapisywanie danych. Kontekst bazy danych pochodzi z elementu Microsoft.EntityFrameworkCore.DbContext i określa jednostki do uwzględnienia w modelu danych.
Tworzenie szkieletu Data/MvcMovieContext.cs
powoduje utworzenie klasy kontekstu bazy danych:
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; }
}
}
Powyższy kod tworzy właściwość DbSet<Movie> reprezentującą filmy w bazie danych.
ASP.NET Core jest kompilowany przy użyciu wstrzykiwania zależności (DI). Usługi, takie jak kontekst bazy danych, muszą być zarejestrowane w usłudze DI w systemie Startup
. Składniki, które wymagają tych usług, są dostarczane za pomocą parametrów konstruktora.
Controllers/MoviesController.cs
W pliku konstruktor używa wstrzykiwania zależności, aby wstrzyknąć MvcMovieContext
kontekst bazy danych do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Tworzenie szkieletu wygenerowało następujący wyróżniony kod w pliku Startup.ConfigureServices
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}
System konfiguracji ASP.NET Core odczytuje bazę danych "MvcTextContext" parametry połączenia.
Badanie wygenerowanej bazy danych parametry połączenia
Tworzenie szkieletu dodało parametry połączenia do appsettings.json
pliku:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
W przypadku programowania lokalnego system konfiguracji ASP.NET Core odczytuje ConnectionString
klucz z appsettings.json
pliku.
Klasa InitialCreate
Migrations/{timestamp}_InitialCreate.cs
Sprawdź plik migracji:
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");
}
}
Powyższy kod:
InitialCreate.Up
Tworzy tabelę Movie i konfigurujeId
jako klucz podstawowy.InitialCreate.Down
Przywraca zmiany schematu wprowadzone przez migracjęUp
.
Wstrzykiwanie zależności w kontrolerze
Controllers/MoviesController.cs
Otwórz plik i sprawdź konstruktor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Konstruktor używa wstrzykiwania zależności do wstrzykiwania kontekstu bazy danych (MvcMovieContext
) do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Przetestuj stronę Tworzenie . Wprowadź i prześlij dane.
Przetestuj strony Edytuj, Szczegóły i Usuń .
Silnie typizowane modele i @model
dyrektywa
Wcześniej w tym samouczku pokazano, jak kontroler może przekazywać dane lub obiekty do widoku przy użyciu słownika ViewData
. Słownik ViewData
jest obiektem dynamicznym, który zapewnia wygodny, opóźniony sposób przekazywania informacji do widoku.
MvC umożliwia przekazywanie silnie typiowanych obiektów modelu do widoku. To silnie typizowane podejście umożliwia sprawdzanie kodu czasu kompilacji. Mechanizm tworzenia szkieletów przekazał silnie typizowanego modelu w MoviesController
klasie i widokach.
Sprawdź wygenerowaną Details
metodę w Controllers/MoviesController.cs
pliku:
// 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);
}
Parametr id
jest zwykle przekazywany jako dane trasy. Na przykład https://localhost:5001/movies/details/1
zestawy:
- Kontroler kontrolera
movies
, pierwszy segment adresu URL. - Akcja na
details
, drugi segment adresu URL. - Od
id
1 do ostatniego segmentu adresu URL.
Element id
można przekazać za pomocą ciągu zapytania, jak w poniższym przykładzie:
https://localhost:5001/movies/details?id=1
Parametr id
jest definiowany jako typ dopuszczalny do wartości null (int?
) w przypadkach, gdy wartość nie jest podana id
.
Wyrażenie lambda jest przekazywane do FirstOrDefaultAsync metody , aby wybrać jednostki filmu zgodne z danymi trasy lub wartością ciągu zapytania.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Jeśli zostanie znaleziony film, wystąpienie Movie
modelu zostanie przekazane do Details
widoku:
return View(movie);
Sprawdź zawartość Views/Movies/Details.cshtml
pliku:
@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>
Instrukcja @model
w górnej części pliku widoku określa typ obiektu, którego oczekuje widok. Po utworzeniu kontrolera filmu dołączono następującą @model
instrukcję:
@model MvcMovie.Models.Movie
Ta @model
dyrektywa umożliwia dostęp do filmu przekazanego przez kontroler do widoku. Obiekt Model
jest silnie typizowane. Na przykład w Details.cshtml
widoku kod przekazuje każde pole filmu do DisplayNameFor
pomocników HTML z DisplayFor
silnie typiowanym Model
obiektem. Metody Create
i Edit
oraz widoki również przekazują Movie
obiekt modelu.
Sprawdź widok i metodę Index.cshtml
Index
w kontrolerze Filmy. Zwróć uwagę, że kod tworzy List
obiekt, gdy wywołuje metodę View
. Kod przekazuje tę Movies
listę z Index
metody akcji do widoku:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Po utworzeniu kontrolera filmów szkielet zawiera następującą @model
instrukcję w górnej Index.cshtml
części pliku:
@model IEnumerable<MvcMovie.Models.Movie>
Dyrektywa @model
umożliwia dostęp do listy filmów przekazywanych przez kontroler do widoku przy użyciu silnie typizowanego Model
obiektu. Na przykład w Index.cshtml
widoku kod przechodzi przez filmy za pomocą foreach
instrukcji na silnie typizowanego Model
obiektu:
@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>
Model
Ponieważ obiekt jest silnie typowany jako IEnumerable<Movie>
obiekt, każdy element w pętli jest wpisywany jako Movie
. Między innymi kompilator weryfikuje typy używane w kodzie.
Rejestrowanie SQL platformy Entity Framework Core
Konfiguracja rejestrowania jest często dostarczana za pomocą sekcji Logging
plików appsettings.{Environment}.json
. Aby zarejestrować instrukcje SQL, dodaj "Microsoft.EntityFrameworkCore.Database.Command": "Information"
do appsettings.Development.json
pliku:
{
"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": "*"
}
Po wcześniejszym kodzie JSON instrukcje SQL są wyświetlane w wierszu polecenia i w oknie danych wyjściowych programu Visual Studio.
Aby uzyskać więcej informacji, zobacz Rejestrowanie na platformie .NET Core i ASP.NET Core oraz ten problem z usługą GitHub.
Dodatkowe zasoby
W tym samouczku klasy są dodawane do zarządzania filmami w bazie danych. Te klasy są częścią "odel" aplikacji MVC.
Te klasy modeli są używane z programem Entity Framework Core (EF Core) do pracy z bazą danych. EF Core to struktura mapowania relacyjnego (ORM, object-relational mapping), która upraszcza kod dostępu do danych, który trzeba napisać.
Utworzone klasy modeli są nazywane klasami POCO z Plain Old CLR Objects. Klasy POCO nie mają żadnej zależności od EF Coreklasy . Definiują tylko właściwości danych, które mają być przechowywane w bazie danych.
W tym samouczku klasy modeli są tworzone najpierw i EF Core tworzy bazę danych.
Dodawanie klasy modelu danych
Kliknij prawym przyciskiem myszy folder >Models Dodaj>klasę. Nazwij plik Movie.cs
.
Movie.cs
Zaktualizuj plik przy użyciu następującego kodu:
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; }
}
}
Klasa Movie
zawiera Id
pole wymagane przez bazę danych dla klucza podstawowego.
Atrybut DataType on ReleaseDate
określa typ danych (Date
). Za pomocą tego atrybutu:
- Użytkownik nie musi wprowadzać informacji o godzinie w polu daty.
- Wyświetlana jest tylko data, a nie informacje o godzinie.
Adnotacje danych zostały omówione w późniejszym samouczku.
Dodawanie pakietów NuGet
Z menu Narzędzia wybierz pozycję NuGet Menedżer pakietów> Menedżer pakietów Konsola (PMC).
W usłudze PMC uruchom następujące polecenie:
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Poprzednie polecenie dodaje dostawcę EF Core programu SQL Server. Pakiet dostawcy EF Core instaluje pakiet jako zależność. Dodatkowe pakiety są instalowane automatycznie w kroku tworzenia szkieletu w dalszej części samouczka.
Tworzenie klasy kontekstu bazy danych
Klasa kontekstu bazy danych jest wymagana do koordynowania EF Core funkcjonalności (Tworzenie, odczyt, aktualizacja, usuwanie) dla Movie
modelu. Kontekst bazy danych pochodzi z Microsoft.EntityFrameworkCore.DbContext i określa jednostki do uwzględnienia w modelu danych.
Utwórz folder Dane.
Data/MvcMovieContext.cs
Dodaj plik z następującym kodem:
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; }
}
}
Powyższy kod tworzy właściwość DbSet<Movie> dla zestawu jednostek. W terminologii platformy Entity Framework zestaw jednostek zwykle odpowiada tabeli bazy danych. Jednostka odpowiada wierszowi w tabeli.
Rejestrowanie kontekstu bazy danych
ASP.NET Core jest kompilowany przy użyciu wstrzykiwania zależności (DI). Usługi (takie jak kontekst bazy danych) muszą być zarejestrowane z di podczas uruchamiania EF Core aplikacji. Składniki, które wymagają tych usług (takich jak Razor Pages), są udostępniane za pomocą parametrów konstruktora. Kod konstruktora, który pobiera wystąpienie kontekstu bazy danych, jest wyświetlany w dalszej części samouczka. W tej sekcji zarejestrujesz kontekst bazy danych w kontenerze DI.
Dodaj następujące using
instrukcje w górnej części elementu Startup.cs
:
using MvcMovie.Data;
using Microsoft.EntityFrameworkCore;
Dodaj następujący wyróżniony kod w Startup.ConfigureServices
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}
Nazwa parametry połączenia jest przekazywana do kontekstu przez wywołanie metody w DbContextOptions obiekcie. W przypadku programowania lokalnego system konfiguracji ASP.NET Core odczytuje parametry połączenia z appsettings.json
pliku.
Badanie parametry połączenia bazy danych
Dodaj parametry połączenia do appsettings.json
pliku:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Skompiluj projekt jako sprawdzenie błędów kompilatora.
Strony filmów szkieletowych
Użyj narzędzia do tworzenia szkieletów, aby tworzyć strony tworzenia, odczytu, aktualizacji i usuwania (CRUD) dla modelu filmu.
W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder > Kontrolery Dodaj > nowy element szkieletowy.
W oknie dialogowym Dodawanie szkieletu wybierz pozycję Kontroler MVC z widokami, używając polecenia Entity Framework > Add.
Ukończ okno dialogowe Dodawanie kontrolera:
- Klasa modelu: Movie (MvcFilm.Models)
- Klasa kontekstu danych: MvcFilmContext (MvcFilm.Data)
- Widoki: pozostaw zaznaczoną wartość domyślną każdej opcji
- Nazwa kontrolera: Zachowaj domyślny kontroler MoviesController
- Wybierz Dodaj
Program Visual Studio tworzy:
- Kontroler filmów (
Controllers/MoviesController.cs
) - Razor wyświetlanie plików dla stron tworzenia, usuwania, szczegółów, edycji i indeksu (*Views/Movies/'.cshtml')
Automatyczne tworzenie tych plików jest nazywane tworzeniem szkieletów.
Nie można jeszcze używać stron szkieletowych, ponieważ baza danych nie istnieje. Jeśli uruchomisz aplikację i klikniesz link Aplikacja filmowa, otrzymasz komunikat o błędzie Nie można otworzyć bazy danych lub nie ma takiej tabeli: Film .
Migracja początkowa
EF CoreUżyj funkcji Migracje, aby utworzyć bazę danych. Migracje to zestaw narzędzi, które umożliwiają tworzenie i aktualizowanie bazy danych w celu dopasowania ich do modelu danych.
Z menu Narzędzia wybierz pozycję NuGet Menedżer pakietów> Menedżer pakietów Konsola (PMC).
W usłudze PMC wprowadź następujące polecenia:
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: generujeMigrations/{timestamp}_InitialCreate.cs
plik migracji. ArgumentemInitialCreate
jest nazwa migracji. Można użyć dowolnej nazwy, ale zgodnie z konwencją wybrana jest nazwa opisującą migrację. Ponieważ jest to pierwsza migracja, wygenerowana klasa zawiera kod umożliwiający utworzenie schematu bazy danych. Schemat bazy danych jest oparty na modelu określonym wMvcMovieContext
klasie.Update-Database
: aktualizuje bazę danych do najnowszej migracji, która została utworzona przez poprzednie polecenie. To polecenie uruchamia metodęUp
wMigrations/{time-stamp}_InitialCreate.cs
pliku, która tworzy bazę danych.Polecenie aktualizacji bazy danych generuje następujące ostrzeżenie:
Nie określono typu dla kolumny dziesiętnej "Price" w typie jednostki "Movie". Spowoduje to dyskretne obcięcie wartości, jeśli nie mieszczą się w domyślnej precyzji i skali. Jawnie określ typ kolumny serwera SQL, który może pomieścić wszystkie wartości przy użyciu polecenia "HasColumnType()".
To ostrzeżenie można zignorować. Zostanie ono naprawione w późniejszym samouczku.
Aby uzyskać więcej informacji na temat narzędzi PMC dla EF Coreprogramu , zobacz EF Core dokumentacja narzędzi — PMC w programie Visual Studio.
InitialCreate, klasa
Migrations/{timestamp}_InitialCreate.cs
Sprawdź plik migracji:
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");
}
}
Metoda Up
tworzy tabelę Movie i konfiguruje Id
jako klucz podstawowy. Metoda Down
przywraca zmiany schematu wprowadzone przez migrację Up
.
Testowanie aplikacji
Uruchom aplikację i kliknij link Aplikacja filmowa.
Jeśli wystąpi wyjątek podobny do jednego z następujących:
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Prawdopodobnie pominięto krok migracji.
Przetestuj stronę Tworzenie . Wprowadź i prześlij dane.
Uwaga
W polu może nie być możliwe wprowadzenie przecinków dziesiętnych
Price
. Aby obsługiwać walidację jQuery dla ustawień regionalnych innych niż angielski, które używają przecinka (",") dla punktu dziesiętnego i w formatach dat innych niż angielskie stany USA, aplikacja musi zostać zglobalizowana. Aby uzyskać instrukcje dotyczące globalizacji, zobacz ten problem z usługą GitHub.Przetestuj strony Edytuj, Szczegóły i Usuń .
Wstrzykiwanie zależności w kontrolerze
Controllers/MoviesController.cs
Otwórz plik i sprawdź konstruktor:
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Konstruktor używa wstrzykiwania zależności do wstrzykiwania kontekstu bazy danych (MvcMovieContext
) do kontrolera. Kontekst bazy danych jest używany w każdej z metod CRUD w kontrolerze.
Silnie typizowane modele i @model słowo kluczowe
Wcześniej w tym samouczku pokazano, jak kontroler może przekazywać dane lub obiekty do widoku przy użyciu słownika ViewData
. Słownik ViewData
jest obiektem dynamicznym, który zapewnia wygodny, opóźniony sposób przekazywania informacji do widoku.
MvC zapewnia również możliwość przekazywania silnie typiowanych obiektów modelu do widoku. To silnie typizowane podejście umożliwia sprawdzanie kodu czasu kompilacji. Mechanizm tworzenia szkieletów używał tego podejścia (czyli przekazywania silnie typizowanego MoviesController
modelu) z klasą i widokami.
Sprawdź wygenerowaną Details
metodę w Controllers/MoviesController.cs
pliku:
// 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);
}
Parametr id
jest zwykle przekazywany jako dane trasy. Na przykład https://localhost:5001/movies/details/1
zestawy:
- Kontroler do
movies
kontrolera (pierwszy segment adresu URL). - Akcja na
details
(drugi segment adresu URL). - Identyfikator na 1 (ostatni segment adresu URL).
Możesz również przekazać element id
za pomocą ciągu zapytania w następujący sposób:
https://localhost:5001/movies/details?id=1
Parametr id
jest definiowany jako typ dopuszczalny wartości null (int?
) w przypadku, gdy wartość identyfikatora nie jest podana.
Wyrażenie lambda jest przekazywane do, aby FirstOrDefaultAsync
wybrać jednostki filmu, które pasują do danych trasy lub wartości ciągu zapytania.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Jeśli zostanie znaleziony film, wystąpienie Movie
modelu zostanie przekazane do Details
widoku:
return View(movie);
Sprawdź zawartość Views/Movies/Details.cshtml
pliku:
@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>
Instrukcja @model
w górnej części pliku widoku określa typ obiektu, którego oczekuje widok. Po utworzeniu kontrolera filmu dołączono następującą @model
instrukcję:
@model MvcMovie.Models.Movie
Ta @model
dyrektywa umożliwia dostęp do filmu przekazanego przez kontroler do widoku. Obiekt Model
jest silnie typizowane. Na przykład w Details.cshtml
widoku kod przekazuje każde pole filmu do DisplayNameFor
pomocników HTML z DisplayFor
silnie typiowanym Model
obiektem. Metody Create
i Edit
oraz widoki również przekazują Movie
obiekt modelu.
Sprawdź widok i metodę Index.cshtml
Index
w kontrolerze Filmy. Zwróć uwagę, że kod tworzy List
obiekt, gdy wywołuje metodę View
. Kod przekazuje tę Movies
listę z Index
metody akcji do widoku:
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Po utworzeniu kontrolera filmów szkielet zawiera następującą @model
instrukcję w górnej Index.cshtml
części pliku:
@model IEnumerable<MvcMovie.Models.Movie>
Dyrektywa @model
umożliwia dostęp do listy filmów przekazywanych przez kontroler do widoku przy użyciu obiektu silnie typizowanego Model
. Na przykład w Index.cshtml
widoku kod przechodzi przez filmy za pomocą foreach
instrukcji na silnie typizowanego Model
obiektu:
@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>
Model
Ponieważ obiekt jest silnie typowany (jako IEnumerable<Movie>
obiekt), każdy element w pętli jest typowany jako Movie
. Między innymi oznacza to, że uzyskujesz sprawdzanie czasu kompilacji kodu.