Événements
31 mars, 23 h - 2 avr., 23 h
L’événement de la communauté Microsoft Fabric, Power BI, SQL et AI ultime. 31 mars au 2 avril 2025.
Inscrivez-vous aujourd’huiCe navigateur n’est plus pris en charge.
Effectuez une mise à niveau vers Microsoft Edge pour tirer parti des dernières fonctionnalités, des mises à jour de sécurité et du support technique.
Notes
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 9 de cet article.
Avertissement
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la stratégie de support .NET et .NET Core. Pour la version actuelle, consultez la version .NET 9 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 9 de cet article.
Par Rick Anderson et Jon P Smith.
Dans ce tutoriel, des classes sont ajoutées pour la gestion des films dans une base de données. Ces classes constituent la partie « Modèle » de l’application MVC.
Ces classes de modèle sont utilisées avec Entity Framework Core (EF Core) pour utiliser une base de données. EF Core est une infrastructure de mappage relationnel d’objets qui simplifie le code d’accès aux données à écrire.
Les classes du modèle créées sont appelées classes POCO, à partir de Plain Old CLR Objects. Les classes POCO n’ont aucune dépendance vis-à-vis de EF Core. Elles définissent uniquement les propriétés des données qui seront stockées dans la base de données.
Dans ce tutoriel, les classes du modèle sont d’abord créées, puis EF Core crée la base de données.
Cliquez avec le bouton droit sur le dossier Modèles >Ajouter>Classe. Nommez le fichier Movie.cs
.
Mettez à jour le fichier Models/Movie.cs
avec le code suivant :
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; }
}
La classe Movie
contient un champ Id
, qui est nécessaire à la base de données pour la clé primaire.
L’attribut DataType de ReleaseDate
spécifie le type de données (Date
). Avec cet attribut :
Les DataAnnotations sont traitées dans un prochain didacticiel.
La présence du point d’interrogation après string
indique que la propriété peut accepter les valeurs Null. Pour plus d’informations, consultez Types référence pouvant accepter la valeur Null.
Visual Studio installe automatiquement les packages requis.
Générez le projet en tant que vérification des erreurs du compilateur.
Utilisez l’outil de génération de modèles automatique pour Create
, Read
, Update
, et Delete
des pages du modèle de film.
Cliquez avec le bouton droit sur le dossier Contrôleurs dans l’Explorateur de solutions, puis sélectionnez Ajouter > Nouvel élément généré automatiquement.
Dans la boîte de dialogue Ajouter un nouvel élément de modèle généré automatiquement :
Terminez la boîte de dialogue Ajouter un contrôleur MVC avec des vues, à l’aide d’Entity Framework :
Si vous obtenez un message d’erreur, sélectionnez Ajouter une deuxième fois pour réessayer.
La génération de modèles automatique ajoute les packages suivants :
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
La génération automatique crée les éléments suivants :
Controllers/MoviesController.cs
Views/Movies/*.cshtml
Data/MvcMovieContext.cs
La génération de modèles automatique met à jour les éléments suivants :
MvcMovie.csproj
.Program.cs
.appsettings.json
.La création automatique de ces fichiers et mises à jour est appelée génération de modèles automatique.
Les pages générées automatiquement ne peuvent pas encore être utilisées, car la base de données n’existe pas. L’exécution de l’application et la sélection du lien Application vidéo entraînent un message d’erreur Impossible d’ouvrir la base de données ou Le type de table suivant n’existe pas : Film.
Générez l’application pour vérifier qu’il n’y a pas d’erreurs.
Utilisez la fonctionnalité EF CoreMigrations pour créer la base de données. La fonctionnalité Migrations est un ensemble d’outils qui vous permettent de créer et de mettre à jour une base de données pour qu’elle corresponde à votre modèle de données.
Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du gestionnaire de package.
Dans la console du Gestionnaire de package (PMC), entrez la commande suivante :
Add-Migration InitialCreate
Add-Migration InitialCreate
: Génère un Migrations/{timestamp}_InitialCreate.cs
fichier de migration. L’argument InitialCreate
est le nom de la migration. Vous pouvez utiliser n’importe quel nom, mais par convention, un nom décrivant la migration est sélectionné. Étant donné qu’il s’agit de la première migration, la classe générée contient du code permettant de créer le schéma de la base de données. Le schéma de base de données est basé sur le modèle spécifié dans la classe MvcMovieContext
.L’avertissement suivant s’affiche et sera traité dans une étape ultérieure :
Aucun type de magasin n’a été spécifié pour la propriété décimale « Price » sur le type d’entité « Movie ». Les valeurs sont tronquées en mode silencieux si elles ne sont pas compatibles avec la précision et l’échelle par défaut. Spécifiez explicitement le type de colonne SQL Server qui peut prendre en charge toutes les valeurs dans « OnModelCreating » à l’aide de « HasColumnType », spécifiez la précision et l’échelle à l’aide de « HasPrecision » ou configurez un convertisseur de valeurs à l’aide de « HasConversion ».
Dans la console PMC, entrez la commande suivante :
Update-Database
Update-Database
: Met à jour la base de données vers la dernière migration, qui a été créée par la commande précédente. Cette commande exécute la méthode Up
dans le fichier Migrations/{time-stamp}_InitialCreate.cs
, qui crée la base de données.Pour plus d’informations sur les outils de la console du gestionnaire de package pour EF Core, consultez EF Core référence sur les outils - Console du gestionnaire de package dans Visual Studio.
Exécutez l’application et sélectionnez sur le lien Movie App.
Si vous obtenez une exception semblable à ce qui suit, vous avez peut-être manqué la commande Update-Database
à l’étape des migrations :
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Notes
Vous ne pourrez peut-être pas entrer de virgules décimales dans le champ Price
. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que « Anglais » qui utilisent une virgule (« , ») comme décimale et des formats de date autres que le format « Anglais (États-Unis »), l’application doit être localisée. Pour obtenir des instructions sur la localisation, consultez ce problème GitHub.
Avec EF Core, l’accès aux données est effectué à l’aide d’un modèle. Un modèle est constitué de classes d’entité et d’un objet de contexte qui représente une session avec la base de données. L’objet de contexte permet l’interrogation et l’enregistrement des données. Le contexte de base de données est dérivé de Microsoft.EntityFrameworkCore.DbContext et il spécifie les entités à inclure dans le modèle de données.
La génération de modèles crée la classe Data/MvcMovieContext.cs
de contexte de base de données :
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!;
}
}
Le code précédent crée une propriété DbSet<Movie> qui représente les films dans la base de données.
ASP.NET Core comprend l’injection de dépendances (DI). Les services, tels que le contexte de base de données, sont inscrits avec une injection de dépendance dans Program.cs
. Ces services sont fournis aux composants qui en ont besoin via des paramètres de constructeur.
Dans le fichier Controllers/MoviesController.cs
, le constructeur utilise une injection de dépendance pour injecter le contexte de base de données MvcMovieContext
dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
La génération de modèles a généré le code en surbrillance suivant dans 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.")));
Le système de configuration ASP.NET Core lit la chaîne de connexion de base de données « MvcMovieContext ».
La génération de modèles a ajouté une chaîne de connexion au fichier appsettings.json
:
{
"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"
}
}
Pour le développement local, le système de configuration ASP.NET Core lit la clé ConnectionString
depuis le fichier appsettings.json
.
Examinez le fichier de migration Migrations/{timestamp}_InitialCreate.cs
:
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
Dans le code précédent :
InitialCreate.Up
crée la table Film et configure Id
comme la clé primaire.InitialCreate.Down
rétablit les modifications de schéma provoquées par la migration Up
.Ouvrez le fichier Controllers/MoviesController.cs
et examinez le constructeur :
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Le constructeur utilise une injection de dépendance pour injecter le contexte de base de données (MvcMovieContext
) dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
Testez la page Create. Entrez et envoyez des données.
Testez les pages Edit, Details et Delete.
Plus tôt dans ce didacticiel, vous avez vu comment un contrôleur peut passer des données ou des objets à une vue en utilisant le dictionnaire ViewData
. Le dictionnaire ViewData
est un objet dynamique qui fournit un moyen pratique d’effectuer une liaison tardive pour passer des informations à une vue.
Le modèle MVC fournit la possibilité de passer des objets de modèle fortement typés à une vue. Cette approche fortement typée permet de vérifier votre code au moment de la compilation. Le mécanisme de génération de modèles a passé un modèle fortement typé dans la classe et les vues MoviesController
.
Examinez la méthode Details
générée dans le fichier Controllers/MoviesController.cs
:
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le paramètre id
est généralement passé en tant que données de routage. Par exemple, https://localhost:5001/movies/details/1
définit :
movies
, le premier segment de l’URL.details
, le deuxième segment de l’URL.id
à 1, le dernier segment d’URL.Le id
peut être transmis avec une chaîne de requête, comme dans l’exemple suivant :
https://localhost:5001/movies/details?id=1
Le paramètre id
est défini comme type Nullable (int?
) au cas où la valeur id
n’est pas fournie.
Une expression lambda est passée à la méthode FirstOrDefaultAsync pour sélectionner les entités de film qui correspondent aux données de routage ou à la valeur de la chaîne de requête.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Si un film est trouvé, une instance du modèle Movie
est passée à la vue Details
:
return View(movie);
Examinez le contenu du fichier Views/Movies/Details.cshtml
:
@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>
L’instruction @model
située en haut du fichier de la vue spécifie le type d’objet attendu par la vue. Lorsque le contrôleur de film était créé, l’instruction @model
suivante était incluse :
@model MvcMovie.Models.Movie
Cette directive @model
autorise l’accès au film que le contrôleur a passé à la vue. L’objet Model
est fortement typé. Par exemple, dans la vue Details.cshtml
, le code passe chaque champ du film aux Helpers HTML DisplayNameFor
et DisplayFor
avec l’objet Model
fortement typé. Les méthodes et les vues Create
et Edit
passent aussi un objet du modèle Movie
.
Examinez la vue Index.cshtml
et la méthode Index
dans le contrôleur Movies. Notez comment le code crée un objet List
quand il appelle la méthode View
. Le code passe cette liste Movies
de la méthode d’action Index
à la vue :
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Le code retourne les détails du problème si la propriété Movie
du contexte de données est null.
Lors de la création du contrôleur du film, la génération de modèles automatique a inclus l’instruction @model
suivante en haut du fichier Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
La directive @model
permet d’accéder à la liste des films que le contrôleur a passé à la vue en utilisant un objet Model
qui est fortement typé. Par exemple, dans la vue Index.cshtml
, le code boucle dans les films avec une instruction foreach
sur l’objet Model
fortement typé :
@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>
Comme l’objet Model
est fortement typé en tant qu’objet IEnumerable<Movie>
, chaque élément de la boucle est typé en tant que Movie
. Entre autres avantages, le compilateur valide les types utilisés dans le code.
Dans ce tutoriel, des classes sont ajoutées pour la gestion des films dans une base de données. Ces classes constituent la partie « Modèle » de l’application MVC.
Ces classes de modèle sont utilisées avec Entity Framework Core (EF Core) pour utiliser une base de données. EF Core est une infrastructure de mappage relationnel d’objets qui simplifie le code d’accès aux données à écrire.
Les classes du modèle créées sont appelées classes POCO, à partir de Plain Old CLR Objects. Les classes POCO n’ont aucune dépendance vis-à-vis de EF Core. Elles définissent uniquement les propriétés des données qui seront stockées dans la base de données.
Dans ce tutoriel, les classes du modèle sont d’abord créées, puis EF Core crée la base de données.
Cliquez avec le bouton droit sur le dossier Modèles >Ajouter>Classe. Nommez le fichier Movie.cs
.
Mettez à jour le fichier Models/Movie.cs
avec le code suivant :
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; }
}
La classe Movie
contient un champ Id
, qui est nécessaire à la base de données pour la clé primaire.
L’attribut DataType de ReleaseDate
spécifie le type de données (Date
). Avec cet attribut :
Les DataAnnotations sont traitées dans un prochain didacticiel.
La présence du point d’interrogation après string
indique que la propriété peut accepter les valeurs Null. Pour plus d’informations, consultez Types référence pouvant accepter la valeur Null.
Visual Studio installe automatiquement les packages requis.
Générez le projet en tant que vérification des erreurs du compilateur.
Utilisez l’outil de génération de modèles automatique pour Create
, Read
, Update
, et Delete
des pages du modèle de film.
Cliquez avec le bouton droit sur le dossier Contrôleurs dans l’Explorateur de solutions, puis sélectionnez Ajouter > Nouvel élément généré automatiquement.
Dans la boîte de dialogue Ajouter un nouvel élément de modèle généré automatiquement :
Terminez la boîte de dialogue Ajouter un contrôleur MVC avec des vues, à l’aide d’Entity Framework :
Si vous obtenez un message d’erreur, sélectionnez Ajouter une deuxième fois pour réessayer.
La génération de modèles automatique ajoute les packages suivants :
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
La génération automatique crée les éléments suivants :
Controllers/MoviesController.cs
Views/Movies/*.cshtml
Data/MvcMovieContext.cs
La génération de modèles automatique met à jour les éléments suivants :
MvcMovie.csproj
.Program.cs
.appsettings.json
.La création automatique de ces fichiers et mises à jour est appelée génération de modèles automatique.
Les pages générées automatiquement ne peuvent pas encore être utilisées, car la base de données n’existe pas. L’exécution de l’application et la sélection du lien Application vidéo entraînent un message d’erreur Impossible d’ouvrir la base de données ou Le type de table suivant n’existe pas : Film.
Générez l’application pour vérifier qu’il n’y a pas d’erreurs.
Utilisez la fonctionnalité EF CoreMigrations pour créer la base de données. La fonctionnalité Migrations est un ensemble d’outils qui vous permettent de créer et de mettre à jour une base de données pour qu’elle corresponde à votre modèle de données.
Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du gestionnaire de package.
Dans la console du Gestionnaire de package, entrez les commandes suivantes :
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: Génère un fichier de migration Migrations/{timestamp}_InitialCreate.cs
. L’argument InitialCreate
est le nom de la migration. Vous pouvez utiliser n’importe quel nom, mais par convention, un nom décrivant la migration est sélectionné. Étant donné qu’il s’agit de la première migration, la classe générée contient du code permettant de créer le schéma de la base de données. Le schéma de base de données est basé sur le modèle spécifié dans la classe MvcMovieContext
.
Update-Database
: Met à jour la base de données vers la dernière migration, qui a été créée par la commande précédente. Cette commande exécute la méthode Up
dans le fichier Migrations/{time-stamp}_InitialCreate.cs
, qui crée la base de données.
La commande Update-Database
génère l’avertissement suivant :
Aucun type de magasin n’a été spécifié pour la propriété décimale « Price » sur le type d’entité « Movie ». Les valeurs sont tronquées en mode silencieux si elles ne sont pas compatibles avec la précision et l’échelle par défaut. Spécifiez explicitement le type de colonne SQL Server qui peut prendre en charge toutes les valeurs dans « OnModelCreating » à l’aide de « HasColumnType », spécifiez la précision et l’échelle à l’aide de « HasPrecision » ou configurez un convertisseur de valeurs à l’aide de « HasConversion ».
Ignorez l’avertissement précédent, il est résolu dans un tutoriel ultérieur.
Pour plus d’informations sur les outils de la console du gestionnaire de package pour EF Core, consultez EF Core référence sur les outils - Console du gestionnaire de package dans Visual Studio.
Exécutez l’application et sélectionnez sur le lien Movie App.
Si vous obtenez une exception semblable à ce qui suit, vous avez peut-être manqué la commande Update-Database
à l’étape des migrations :
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Notes
Vous ne pourrez peut-être pas entrer de virgules décimales dans le champ Price
. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que « Anglais » qui utilisent une virgule (« , ») comme décimale et des formats de date autres que le format « Anglais (États-Unis »), l’application doit être localisée. Pour obtenir des instructions sur la localisation, consultez ce problème GitHub.
Avec EF Core, l’accès aux données est effectué à l’aide d’un modèle. Un modèle est constitué de classes d’entité et d’un objet de contexte qui représente une session avec la base de données. L’objet de contexte permet l’interrogation et l’enregistrement des données. Le contexte de base de données est dérivé de Microsoft.EntityFrameworkCore.DbContext et il spécifie les entités à inclure dans le modèle de données.
La génération de modèles crée la classe Data/MvcMovieContext.cs
de contexte de base de données :
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; }
}
}
Le code précédent crée une propriété DbSet<Movie> qui représente les films dans la base de données.
ASP.NET Core comprend l’injection de dépendances (DI). Les services, tels que le contexte de base de données, sont inscrits avec une injection de dépendance dans Program.cs
. Ces services sont fournis aux composants qui en ont besoin via des paramètres de constructeur.
Dans le fichier Controllers/MoviesController.cs
, le constructeur utilise une injection de dépendance pour injecter le contexte de base de données MvcMovieContext
dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
La génération de modèles a généré le code en surbrillance suivant dans Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
Le système de configuration ASP.NET Core lit la chaîne de connexion de base de données « MvcMovieContext ».
La génération de modèles a ajouté une chaîne de connexion au fichier appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Data Source=MvcMovieContext-ea7a4069-f366-4742-bd1c-3f753a804ce1.db"
}
}
Pour le développement local, le système de configuration ASP.NET Core lit la clé ConnectionString
depuis le fichier appsettings.json
.
Examinez le fichier de migration Migrations/{timestamp}_InitialCreate.cs
:
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
Dans le code précédent :
InitialCreate.Up
crée la table Film et configure Id
comme la clé primaire.InitialCreate.Down
rétablit les modifications de schéma provoquées par la migration Up
.Ouvrez le fichier Controllers/MoviesController.cs
et examinez le constructeur :
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Le constructeur utilise une injection de dépendance pour injecter le contexte de base de données (MvcMovieContext
) dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
Testez la page Create. Entrez et envoyez des données.
Testez les pages Edit, Details et Delete.
Plus tôt dans ce didacticiel, vous avez vu comment un contrôleur peut passer des données ou des objets à une vue en utilisant le dictionnaire ViewData
. Le dictionnaire ViewData
est un objet dynamique qui fournit un moyen pratique d’effectuer une liaison tardive pour passer des informations à une vue.
Le modèle MVC fournit la possibilité de passer des objets de modèle fortement typés à une vue. Cette approche fortement typée permet de vérifier votre code au moment de la compilation. Le mécanisme de génération de modèles a passé un modèle fortement typé dans la classe et les vues MoviesController
.
Examinez la méthode Details
générée dans le fichier Controllers/MoviesController.cs
:
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le paramètre id
est généralement passé en tant que données de routage. Par exemple, https://localhost:5001/movies/details/1
définit :
movies
, le premier segment de l’URL.details
, le deuxième segment de l’URL.id
à 1, le dernier segment d’URL.Le id
peut être transmis avec une chaîne de requête, comme dans l’exemple suivant :
https://localhost:5001/movies/details?id=1
Le paramètre id
est défini comme type Nullable (int?
) au cas où la valeur id
n’est pas fournie.
Une expression lambda est passée à la méthode FirstOrDefaultAsync pour sélectionner les entités de film qui correspondent aux données de routage ou à la valeur de la chaîne de requête.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Si un film est trouvé, une instance du modèle Movie
est passée à la vue Details
:
return View(movie);
Examinez le contenu du fichier Views/Movies/Details.cshtml
:
@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>
L’instruction @model
située en haut du fichier de la vue spécifie le type d’objet attendu par la vue. Lorsque le contrôleur de film était créé, l’instruction @model
suivante était incluse :
@model MvcMovie.Models.Movie
Cette directive @model
autorise l’accès au film que le contrôleur a passé à la vue. L’objet Model
est fortement typé. Par exemple, dans la vue Details.cshtml
, le code passe chaque champ du film aux Helpers HTML DisplayNameFor
et DisplayFor
avec l’objet Model
fortement typé. Les méthodes et les vues Create
et Edit
passent aussi un objet du modèle Movie
.
Examinez la vue Index.cshtml
et la méthode Index
dans le contrôleur Movies. Notez comment le code crée un objet List
quand il appelle la méthode View
. Le code passe cette liste Movies
de la méthode d’action Index
à la vue :
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Le code retourne les détails du problème si la propriété Movie
du contexte de données est null.
Lors de la création du contrôleur du film, la génération de modèles automatique a inclus l’instruction @model
suivante en haut du fichier Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
La directive @model
permet d’accéder à la liste des films que le contrôleur a passé à la vue en utilisant un objet Model
qui est fortement typé. Par exemple, dans la vue Index.cshtml
, le code boucle dans les films avec une instruction foreach
sur l’objet Model
fortement typé :
@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>
Comme l’objet Model
est fortement typé en tant qu’objet IEnumerable<Movie>
, chaque élément de la boucle est typé en tant que Movie
. Entre autres avantages, le compilateur valide les types utilisés dans le code.
Dans ce tutoriel, des classes sont ajoutées pour la gestion des films dans une base de données. Ces classes constituent la partie « Modèle » de l’application MVC.
Ces classes de modèle sont utilisées avec Entity Framework Core (EF Core) pour utiliser une base de données. EF Core est une infrastructure de mappage relationnel d’objets qui simplifie le code d’accès aux données à écrire.
Les classes du modèle créées sont appelées classes POCO, à partir de Plain Old CLR Objects. Les classes POCO n’ont aucune dépendance vis-à-vis de EF Core. Elles définissent uniquement les propriétés des données qui seront stockées dans la base de données.
Dans ce tutoriel, les classes du modèle sont d’abord créées, puis EF Core crée la base de données.
Cliquez avec le bouton droit sur le dossier Modèles >Ajouter>Classe. Nommez le fichier Movie.cs
.
Mettez à jour le fichier Models/Movie.cs
avec le code suivant :
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; }
}
La classe Movie
contient un champ Id
, qui est nécessaire à la base de données pour la clé primaire.
L’attribut DataType de ReleaseDate
spécifie le type de données (Date
). Avec cet attribut :
Les DataAnnotations sont traitées dans un prochain didacticiel.
La présence du point d’interrogation après string
indique que la propriété peut accepter les valeurs Null. Pour plus d’informations, consultez Types référence pouvant accepter la valeur Null.
Visual Studio installe automatiquement les packages requis.
Générez le projet en tant que vérification des erreurs du compilateur.
Utilisez l’outil de génération de modèles automatique pour Create
, Read
, Update
, et Delete
des pages du modèle de film.
Cliquez avec le bouton droit sur le dossier Contrôleurs dans l’Explorateur de solutions, puis sélectionnez Ajouter > Nouvel élément généré automatiquement.
Dans la boîte de dialogue Ajouter un nouvel élément de modèle généré automatiquement :
Terminez la boîte de dialogue Ajouter un contrôleur MVC avec des vues, à l’aide d’Entity Framework :
Si vous obtenez un message d’erreur, sélectionnez Ajouter une deuxième fois pour réessayer.
La génération de modèles automatique ajoute les packages suivants :
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
Microsoft.VisualStudio.Web.CodeGeneration.Design
La génération automatique crée les éléments suivants :
Controllers/MoviesController.cs
Views/Movies/*.cshtml
Data/MvcMovieContext.cs
La génération de modèles automatique met à jour les éléments suivants :
MvcMovie.csproj
.Program.cs
.appsettings.json
.La création automatique de ces fichiers et mises à jour est appelée génération de modèles automatique.
Les pages générées automatiquement ne peuvent pas encore être utilisées, car la base de données n’existe pas. L’exécution de l’application et la sélection du lien Application vidéo entraînent un message d’erreur Impossible d’ouvrir la base de données ou Le type de table suivant n’existe pas : Film.
Générez l’application pour vérifier qu’il n’y a pas d’erreurs.
Utilisez la fonctionnalité EF CoreMigrations pour créer la base de données. La fonctionnalité Migrations est un ensemble d’outils qui vous permettent de créer et de mettre à jour une base de données pour qu’elle corresponde à votre modèle de données.
Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du gestionnaire de package.
Dans la console du Gestionnaire de package, entrez les commandes suivantes :
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: Génère un fichier de migration Migrations/{timestamp}_InitialCreate.cs
. L’argument InitialCreate
est le nom de la migration. Vous pouvez utiliser n’importe quel nom, mais par convention, un nom décrivant la migration est sélectionné. Étant donné qu’il s’agit de la première migration, la classe générée contient du code permettant de créer le schéma de la base de données. Le schéma de base de données est basé sur le modèle spécifié dans la classe MvcMovieContext
.
Update-Database
: Met à jour la base de données vers la dernière migration, qui a été créée par la commande précédente. Cette commande exécute la méthode Up
dans le fichier Migrations/{time-stamp}_InitialCreate.cs
, qui crée la base de données.
La commande Update-Database
génère l’avertissement suivant :
Aucun type n’a été spécifié pour la colonne décimale 'Price' sur le type d’entité 'Movie'. Les valeurs sont tronquées en mode silencieux si elles ne sont pas compatibles avec la précision et l’échelle par défaut. Spécifiez explicitement le type de colonne SQL Server capable d’accueillir toutes les valeurs en utilisant ’HasColumnType()’.
Ignorez l’avertissement précédent, il est résolu dans un tutoriel ultérieur.
Pour plus d’informations sur les outils de la console du gestionnaire de package pour EF Core, consultez EF Core référence sur les outils - Console du gestionnaire de package dans Visual Studio.
Exécutez l’application et sélectionnez sur le lien Movie App.
Si vous obtenez une exception semblable à ce qui suit, vous avez peut-être manqué la commande Update-Database
à l’étape des migrations :
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Notes
Vous ne pourrez peut-être pas entrer de virgules décimales dans le champ Price
. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que « Anglais » qui utilisent une virgule (« , ») comme décimale et des formats de date autres que le format « Anglais (États-Unis »), l’application doit être localisée. Pour obtenir des instructions sur la localisation, consultez ce problème GitHub.
Avec EF Core, l’accès aux données est effectué à l’aide d’un modèle. Un modèle est constitué de classes d’entité et d’un objet de contexte qui représente une session avec la base de données. L’objet de contexte permet l’interrogation et l’enregistrement des données. Le contexte de base de données est dérivé de Microsoft.EntityFrameworkCore.DbContext et il spécifie les entités à inclure dans le modèle de données.
La génération de modèles crée la classe Data/MvcMovieContext.cs
de contexte de base de données :
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; }
}
}
Le code précédent crée une propriété DbSet<Movie> qui représente les films dans la base de données.
ASP.NET Core comprend l’injection de dépendances (DI). Les services, tels que le contexte de base de données, sont inscrits avec une injection de dépendance dans Program.cs
. Ces services sont fournis aux composants qui en ont besoin via des paramètres de constructeur.
Dans le fichier Controllers/MoviesController.cs
, le constructeur utilise une injection de dépendance pour injecter le contexte de base de données MvcMovieContext
dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
La génération de modèles a généré le code en surbrillance suivant dans Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
Le système de configuration ASP.NET Core lit la chaîne de connexion de base de données « MvcMovieContext ».
La génération de modèles a ajouté une chaîne de connexion au fichier appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Data Source=MvcMovieContext-ea7a4069-f366-4742-bd1c-3f753a804ce1.db"
}
}
Pour le développement local, le système de configuration ASP.NET Core lit la clé ConnectionString
depuis le fichier appsettings.json
.
Examinez le fichier de migration Migrations/{timestamp}_InitialCreate.cs
:
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
Dans le code précédent :
InitialCreate.Up
crée la table Film et configure Id
comme la clé primaire.InitialCreate.Down
rétablit les modifications de schéma provoquées par la migration Up
.Ouvrez le fichier Controllers/MoviesController.cs
et examinez le constructeur :
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Le constructeur utilise une injection de dépendance pour injecter le contexte de base de données (MvcMovieContext
) dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
Testez la page Create. Entrez et envoyez des données.
Testez les pages Edit, Details et Delete.
Plus tôt dans ce didacticiel, vous avez vu comment un contrôleur peut passer des données ou des objets à une vue en utilisant le dictionnaire ViewData
. Le dictionnaire ViewData
est un objet dynamique qui fournit un moyen pratique d’effectuer une liaison tardive pour passer des informations à une vue.
Le modèle MVC fournit la possibilité de passer des objets de modèle fortement typés à une vue. Cette approche fortement typée permet de vérifier votre code au moment de la compilation. Le mécanisme de génération de modèles a passé un modèle fortement typé dans la classe et les vues MoviesController
.
Examinez la méthode Details
générée dans le fichier Controllers/MoviesController.cs
:
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le paramètre id
est généralement passé en tant que données de routage. Par exemple, https://localhost:5001/movies/details/1
définit :
movies
, le premier segment de l’URL.details
, le deuxième segment de l’URL.id
à 1, le dernier segment d’URL.Le id
peut être transmis avec une chaîne de requête, comme dans l’exemple suivant :
https://localhost:5001/movies/details?id=1
Le paramètre id
est défini comme type Nullable (int?
) au cas où la valeur id
n’est pas fournie.
Une expression lambda est passée à la méthode FirstOrDefaultAsync pour sélectionner les entités de film qui correspondent aux données de routage ou à la valeur de la chaîne de requête.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Si un film est trouvé, une instance du modèle Movie
est passée à la vue Details
:
return View(movie);
Examinez le contenu du fichier Views/Movies/Details.cshtml
:
@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>
L’instruction @model
située en haut du fichier de la vue spécifie le type d’objet attendu par la vue. Lorsque le contrôleur de film était créé, l’instruction @model
suivante était incluse :
@model MvcMovie.Models.Movie
Cette directive @model
autorise l’accès au film que le contrôleur a passé à la vue. L’objet Model
est fortement typé. Par exemple, dans la vue Details.cshtml
, le code passe chaque champ du film aux Helpers HTML DisplayNameFor
et DisplayFor
avec l’objet Model
fortement typé. Les méthodes et les vues Create
et Edit
passent aussi un objet du modèle Movie
.
Examinez la vue Index.cshtml
et la méthode Index
dans le contrôleur Movies. Notez comment le code crée un objet List
quand il appelle la méthode View
. Le code passe cette liste Movies
de la méthode d’action Index
à la vue :
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Le code retourne les détails du problème si la propriété Movie
du contexte de données est null.
Lors de la création du contrôleur du film, la génération de modèles automatique a inclus l’instruction @model
suivante en haut du fichier Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
La directive @model
permet d’accéder à la liste des films que le contrôleur a passé à la vue en utilisant un objet Model
qui est fortement typé. Par exemple, dans la vue Index.cshtml
, le code boucle dans les films avec une instruction foreach
sur l’objet Model
fortement typé :
@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>
Comme l’objet Model
est fortement typé en tant qu’objet IEnumerable<Movie>
, chaque élément de la boucle est typé en tant que Movie
. Entre autres avantages, le compilateur valide les types utilisés dans le code.
Dans ce tutoriel, des classes sont ajoutées pour la gestion des films dans une base de données. Ces classes constituent la partie « Modèle » de l’application MVC.
Ces classes de modèle sont utilisées avec Entity Framework Core (EF Core) pour utiliser une base de données. EF Core est une infrastructure de mappage relationnel d’objets qui simplifie le code d’accès aux données à écrire.
Les classes du modèle créées sont appelées classes POCO, à partir de Plain Old CLR Objects. Les classes POCO n’ont aucune dépendance vis-à-vis de EF Core. Elles définissent uniquement les propriétés des données qui seront stockées dans la base de données.
Dans ce tutoriel, les classes du modèle sont d’abord créées, puis EF Core crée la base de données.
Cliquez avec le bouton droit sur le dossier Modèles >Ajouter>Classe. Nommez le fichier Movie.cs
.
Mettez à jour le fichier Models/Movie.cs
avec le code suivant :
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; }
}
}
La classe Movie
contient un champ Id
, qui est nécessaire à la base de données pour la clé primaire.
L’attribut DataType de ReleaseDate
spécifie le type de données (Date
). Avec cet attribut :
Les DataAnnotations sont traitées dans un prochain didacticiel.
La présence du point d’interrogation après string
indique que la propriété peut accepter les valeurs Null. Pour plus d’informations, consultez Types référence pouvant accepter la valeur Null.
Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du gestionnaire de package (PMC).
Dans la console du gestionnaire de package, exécutez la commande suivante :
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Microsoft.EntityFrameworkCore.SqlServer
Les commandes précédentes ajoutent :
Générez le projet en tant que vérification des erreurs du compilateur.
Utilisez l’outil de génération de modèles automatique pour Create
, Read
, Update
, et Delete
des pages du modèle de film.
Cliquez avec le bouton droit sur le dossier Contrôleurs dans l’Explorateur de solutions, puis sélectionnez Ajouter > Nouvel élément généré automatiquement.
Dans la boîte de dialogue Ajouter un modèle automatique, sélectionnez Contrôleur MVC avec vues, utilisant Entity Framework > Ajouter.
Terminez la boîte de dialogue Ajouter un contrôleur MVC avec des vues, à l’aide d’Entity Framework :
Si vous obtenez un message d’erreur, sélectionnez Ajouter une deuxième fois pour réessayer.
La génération de modèles automatique met à jour les éléments suivants :
MvcMovie.csproj
.Program.cs
.appsettings.json
.La génération automatique crée les éléments suivants :
Controllers/MoviesController.cs
Views/Movies/*.cshtml
Data/MvcMovieContext.cs
La création automatique de ces fichiers et mises à jour est appelée génération de modèles automatique.
Les pages générées automatiquement ne peuvent pas encore être utilisées, car la base de données n’existe pas. L’exécution de l’application et la sélection du lien Application vidéo entraînent un message d’erreur Impossible d’ouvrir la base de données ou Le type de table suivant n’existe pas : Film.
Générez l'application. Le compilateur génère plusieurs avertissements sur la façon dont les valeurs null
sont gérées. Pour plus d’informations, consultez ce problème GitHub et les types de référence pouvant accepter la valeur Null.
Pour éliminer les avertissements des types de référence pouvant accepter la valeur Null, supprimez la ligne suivante du fichier MvcMovie.csproj
:
<Nullable>enable</Nullable>
Nous espérons résoudre ce problème dans la prochaine version.
Utilisez la fonctionnalité EF CoreMigrations pour créer la base de données. La fonctionnalité Migrations est un ensemble d’outils qui vous permettent de créer et de mettre à jour une base de données pour qu’elle corresponde à votre modèle de données.
Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du gestionnaire de package.
Dans la console du Gestionnaire de package, entrez les commandes suivantes :
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: Génère un fichier de migration Migrations/{timestamp}_InitialCreate.cs
. L’argument InitialCreate
est le nom de la migration. Vous pouvez utiliser n’importe quel nom, mais par convention, un nom décrivant la migration est sélectionné. Étant donné qu’il s’agit de la première migration, la classe générée contient du code permettant de créer le schéma de la base de données. Le schéma de base de données est basé sur le modèle spécifié dans la classe MvcMovieContext
.
Update-Database
: Met à jour la base de données vers la dernière migration, qui a été créée par la commande précédente. Cette commande exécute la méthode Up
dans le fichier Migrations/{time-stamp}_InitialCreate.cs
, qui crée la base de données.
La commande Update-Database
génère l’avertissement suivant :
Aucun type n’a été spécifié pour la colonne décimale 'Price' sur le type d’entité 'Movie'. Les valeurs sont tronquées en mode silencieux si elles ne sont pas compatibles avec la précision et l’échelle par défaut. Spécifiez explicitement le type de colonne SQL Server capable d’accueillir toutes les valeurs en utilisant ’HasColumnType()’.
Ignorez l’avertissement précédent, il est résolu dans un tutoriel ultérieur.
Pour plus d’informations sur les outils de la console du gestionnaire de package pour EF Core, consultez EF Core référence sur les outils - Console du gestionnaire de package dans Visual Studio.
Exécutez l’application et sélectionnez sur le lien Movie App.
Si vous obtenez une exception similaire à ce qui suit, vous avez peut-être manqué l’étape de migration :
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Notes
Vous ne pourrez peut-être pas entrer de virgules décimales dans le champ Price
. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que « Anglais » qui utilisent une virgule (« , ») comme décimale et des formats de date autres que le format « Anglais (États-Unis »), l’application doit être localisée. Pour obtenir des instructions sur la localisation, consultez ce problème GitHub.
Avec EF Core, l’accès aux données est effectué à l’aide d’un modèle. Un modèle est constitué de classes d’entité et d’un objet de contexte qui représente une session avec la base de données. L’objet de contexte permet l’interrogation et l’enregistrement des données. Le contexte de base de données est dérivé de Microsoft.EntityFrameworkCore.DbContext et il spécifie les entités à inclure dans le modèle de données.
La génération de modèles crée la classe Data/MvcMovieContext.cs
de contexte de base de données :
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; }
}
}
Le code précédent crée une propriété DbSet<Movie> qui représente les films dans la base de données.
ASP.NET Core comprend l’injection de dépendances (DI). Les services, tels que le contexte de base de données, sont inscrits avec une injection de dépendance dans Program.cs
. Ces services sont fournis aux composants qui en ont besoin via des paramètres de constructeur.
Dans le fichier Controllers/MoviesController.cs
, le constructeur utilise une injection de dépendance pour injecter le contexte de base de données MvcMovieContext
dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
La génération de modèles a généré le code en surbrillance suivant dans Program.cs
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("MvcMovieContext")));
Le système de configuration ASP.NET Core lit la chaîne de connexion de base de données « MvcMovieContext ».
La génération de modèles a ajouté une chaîne de connexion au fichier appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-7dc5;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Pour le développement local, le système de configuration ASP.NET Core lit la clé ConnectionString
depuis le fichier appsettings.json
.
Examinez le fichier de migration Migrations/{timestamp}_InitialCreate.cs
:
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace MvcMovie.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
}
Dans le code précédent :
InitialCreate.Up
crée la table Film et configure Id
comme la clé primaire.InitialCreate.Down
rétablit les modifications de schéma provoquées par la migration Up
.Ouvrez le fichier Controllers/MoviesController.cs
et examinez le constructeur :
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Le constructeur utilise une injection de dépendance pour injecter le contexte de base de données (MvcMovieContext
) dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
Testez la page Create. Entrez et envoyez des données.
Testez les pages Edit, Details et Delete.
Plus tôt dans ce didacticiel, vous avez vu comment un contrôleur peut passer des données ou des objets à une vue en utilisant le dictionnaire ViewData
. Le dictionnaire ViewData
est un objet dynamique qui fournit un moyen pratique d’effectuer une liaison tardive pour passer des informations à une vue.
Le modèle MVC fournit la possibilité de passer des objets de modèle fortement typés à une vue. Cette approche fortement typée permet de vérifier votre code au moment de la compilation. Le mécanisme de génération de modèles a passé un modèle fortement typé dans la classe et les vues MoviesController
.
Examinez la méthode Details
générée dans le fichier Controllers/MoviesController.cs
:
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le paramètre id
est généralement passé en tant que données de routage. Par exemple, https://localhost:5001/movies/details/1
définit :
movies
, le premier segment de l’URL.details
, le deuxième segment de l’URL.id
à 1, le dernier segment d’URL.Le id
peut être transmis avec une chaîne de requête, comme dans l’exemple suivant :
https://localhost:5001/movies/details?id=1
Le paramètre id
est défini comme type Nullable (int?
) au cas où la valeur id
n’est pas fournie.
Une expression lambda est passée à la méthode FirstOrDefaultAsync pour sélectionner les entités de film qui correspondent aux données de routage ou à la valeur de la chaîne de requête.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Si un film est trouvé, une instance du modèle Movie
est passée à la vue Details
:
return View(movie);
Examinez le contenu du fichier Views/Movies/Details.cshtml
:
@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>
L’instruction @model
située en haut du fichier de la vue spécifie le type d’objet attendu par la vue. Lorsque le contrôleur de film était créé, l’instruction @model
suivante était incluse :
@model MvcMovie.Models.Movie
Cette directive @model
autorise l’accès au film que le contrôleur a passé à la vue. L’objet Model
est fortement typé. Par exemple, dans la vue Details.cshtml
, le code passe chaque champ du film aux Helpers HTML DisplayNameFor
et DisplayFor
avec l’objet Model
fortement typé. Les méthodes et les vues Create
et Edit
passent aussi un objet du modèle Movie
.
Examinez la vue Index.cshtml
et la méthode Index
dans le contrôleur Movies. Notez comment le code crée un objet List
quand il appelle la méthode View
. Le code passe cette liste Movies
de la méthode d’action Index
à la vue :
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Lors de la création du contrôleur du film, la génération de modèles automatique a inclus l’instruction @model
suivante en haut du fichier Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
La directive @model
permet d’accéder à la liste des films que le contrôleur a passé à la vue en utilisant un objet Model
qui est fortement typé. Par exemple, dans la vue Index.cshtml
, le code boucle dans les films avec une instruction foreach
sur l’objet Model
fortement typé :
@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>
Comme l’objet Model
est fortement typé en tant qu’objet IEnumerable<Movie>
, chaque élément de la boucle est typé en tant que Movie
. Entre autres avantages, le compilateur valide les types utilisés dans le code.
Dans ce tutoriel, des classes sont ajoutées pour la gestion des films dans une base de données. Ces classes constituent la partie « Modèle » de l’application MVC.
Ces classes de modèle sont utilisées avec Entity Framework Core (EF Core) pour utiliser une base de données. EF Core est une infrastructure de mappage relationnel d’objets qui simplifie le code d’accès aux données à écrire.
Les classes du modèle créées sont appelées classes POCO, à partir de Plain Old CLR Objects. Les classes POCO n’ont aucune dépendance vis-à-vis de EF Core. Elles définissent uniquement les propriétés des données qui seront stockées dans la base de données.
Dans ce tutoriel, les classes du modèle sont d’abord créées, puis EF Core crée la base de données.
Cliquez avec le bouton droit sur le dossier Modèles >Ajouter>Classe. Nommez le fichier Movie.cs
.
Mettez à jour le fichier Models/Movie.cs
avec le code suivant :
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; }
}
}
La classe Movie
contient un champ Id
, qui est nécessaire à la base de données pour la clé primaire.
L’attribut DataType de ReleaseDate
spécifie le type de données (Date
). Avec cet attribut :
Les DataAnnotations sont traitées dans un prochain didacticiel.
Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du gestionnaire de package (PMC).
Dans la console du gestionnaire de package, exécutez la commande suivante :
Install-Package Microsoft.EntityFrameworkCore.Design
Les commandes précédentes ajoutent :
Générez le projet en tant que vérification des erreurs du compilateur.
Utilisez l’outil de génération de modèles automatique pour Create
, Read
, Update
, et Delete
des pages du modèle de film.
Cliquez avec le bouton droit sur le dossier Contrôleurs dans l’Explorateur de solutions, puis sélectionnez Ajouter > Nouvel élément généré automatiquement.
Dans la boîte de dialogue Ajouter un modèle automatique, sélectionnez Contrôleur MVC avec vues, utilisant Entity Framework > Ajouter.
Terminez la boîte de dialogue Ajouter un contrôleur MVC avec des vues, à l’aide d’Entity Framework :
La génération de modèles automatique met à jour les éléments suivants :
MvcMovie.csproj
.Startup.ConfigureServices
du fichier Startup.cs
.appsettings.json
.La génération automatique crée les éléments suivants :
Controllers/MoviesController.cs
Views/Movies/*.cshtml
Data/MvcMovieContext.cs
La création automatique de ces fichiers et mises à jour de fichiers est appelée génération de modèles automatique.
Les pages générées automatiquement ne peuvent pas encore être utilisées, car la base de données n’existe pas. L’exécution de l’application et la sélection du lien Application vidéo entraînent un message d’erreur Impossible d’ouvrir la base de données ou Le type de table suivant n’existe pas : Film.
Utilisez la fonctionnalité EF CoreMigrations pour créer la base de données. Les migrations sont un ensemble d’outils qui créent et mettent à jour une base de données pour correspondre au modèle de données.
Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du gestionnaire de package.
Dans la console du Gestionnaire de package, entrez les commandes suivantes :
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: Génère un fichier de migration Migrations/{timestamp}_InitialCreate.cs
. L’argument InitialCreate
est le nom de la migration. Vous pouvez utiliser n’importe quel nom, mais par convention, un nom décrivant la migration est sélectionné. Étant donné qu’il s’agit de la première migration, la classe générée contient du code permettant de créer le schéma de la base de données. Le schéma de base de données est basé sur le modèle spécifié dans la classe MvcMovieContext
.
Update-Database
: Met à jour la base de données vers la dernière migration, qui a été créée par la commande précédente. Cette commande exécute la méthode Up
dans le fichier Migrations/{time-stamp}_InitialCreate.cs
, qui crée la base de données.
La commande Update-Database
génère l’avertissement suivant :
Aucun type n’a été spécifié pour la colonne décimale 'Price' sur le type d’entité 'Movie'. Les valeurs sont tronquées en mode silencieux si elles ne sont pas compatibles avec la précision et l’échelle par défaut. Spécifiez explicitement le type de colonne SQL Server capable d’accueillir toutes les valeurs en utilisant ’HasColumnType()’.
Ignorez l’avertissement précédent, il est résolu dans un tutoriel ultérieur.
Pour plus d’informations sur les outils de la console du gestionnaire de package pour EF Core, consultez EF Core référence sur les outils - Console du gestionnaire de package dans Visual Studio.
Exécutez l’application et sélectionnez sur le lien Movie App.
Si vous obtenez une exception similaire à ce qui suit, vous avez peut-être manqué l’étape de migration :
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Notes
Vous ne pourrez peut-être pas entrer de virgules décimales dans le champ Price
. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que « Anglais » qui utilisent une virgule (« , ») comme décimale et des formats de date autres que le format « Anglais (États-Unis »), l’application doit être localisée. Pour obtenir des instructions sur la localisation, consultez ce problème GitHub.
Avec EF Core, l’accès aux données est effectué à l’aide d’un modèle. Un modèle est constitué de classes d’entité et d’un objet de contexte qui représente une session avec la base de données. L’objet de contexte permet l’interrogation et l’enregistrement des données. Le contexte de base de données est dérivé de Microsoft.EntityFrameworkCore.DbContext et il spécifie les entités à inclure dans le modèle de données.
La génération de modèles crée la classe Data/MvcMovieContext.cs
de contexte de base de données :
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; }
}
}
Le code précédent crée une propriété DbSet<Movie> qui représente les films dans la base de données.
ASP.NET Core comprend l’injection de dépendances (DI). Les services, tels que le contexte de base de données, doivent être inscrits avec l’injection de dépendances dans Startup
. Les composants qui nécessitent ces services sont fournis via des paramètres de constructeur.
Dans le fichier Controllers/MoviesController.cs
, le constructeur utilise une injection de dépendance pour injecter le contexte de base de données MvcMovieContext
dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
La génération de modèles a généré le code en surbrillance suivant dans Startup.ConfigureServices
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}
Le système de configuration ASP.NET Core lit la chaîne de connexion de base de données « MvcMovieContext ».
La génération de modèles a ajouté une chaîne de connexion au fichier appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Pour le développement local, le système de configuration ASP.NET Core lit la clé ConnectionString
depuis le fichier appsettings.json
.
Examinez le fichier de migration Migrations/{timestamp}_InitialCreate.cs
:
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Title = table.Column<string>(type: "nvarchar(max)", nullable: true),
ReleaseDate = table.Column<DateTime>(type: "datetime2", nullable: false),
Genre = table.Column<string>(type: "nvarchar(max)", nullable: true),
Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
Dans le code précédent :
InitialCreate.Up
crée la table Film et configure Id
comme la clé primaire.InitialCreate.Down
rétablit les modifications de schéma provoquées par la migration Up
.Ouvrez le fichier Controllers/MoviesController.cs
et examinez le constructeur :
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Le constructeur utilise une injection de dépendance pour injecter le contexte de base de données (MvcMovieContext
) dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
Testez la page Create. Entrez et envoyez des données.
Testez les pages Edit, Details et Delete.
Plus tôt dans ce didacticiel, vous avez vu comment un contrôleur peut passer des données ou des objets à une vue en utilisant le dictionnaire ViewData
. Le dictionnaire ViewData
est un objet dynamique qui fournit un moyen pratique d’effectuer une liaison tardive pour passer des informations à une vue.
Le modèle MVC fournit la possibilité de passer des objets de modèle fortement typés à une vue. Cette approche fortement typée permet de vérifier votre code au moment de la compilation. Le mécanisme de génération de modèles a passé un modèle fortement typé dans la classe et les vues MoviesController
.
Examinez la méthode Details
générée dans le fichier Controllers/MoviesController.cs
:
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le paramètre id
est généralement passé en tant que données de routage. Par exemple, https://localhost:5001/movies/details/1
définit :
movies
, le premier segment de l’URL.details
, le deuxième segment de l’URL.id
à 1, le dernier segment d’URL.Le id
peut être transmis avec une chaîne de requête, comme dans l’exemple suivant :
https://localhost:5001/movies/details?id=1
Le paramètre id
est défini comme type Nullable (int?
) au cas où la valeur id
n’est pas fournie.
Une expression lambda est passée à la méthode FirstOrDefaultAsync pour sélectionner les entités de film qui correspondent aux données de routage ou à la valeur de la chaîne de requête.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Si un film est trouvé, une instance du modèle Movie
est passée à la vue Details
:
return View(movie);
Examinez le contenu du fichier Views/Movies/Details.cshtml
:
@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>
L’instruction @model
située en haut du fichier de la vue spécifie le type d’objet attendu par la vue. Lorsque le contrôleur de film était créé, l’instruction @model
suivante était incluse :
@model MvcMovie.Models.Movie
Cette directive @model
autorise l’accès au film que le contrôleur a passé à la vue. L’objet Model
est fortement typé. Par exemple, dans la vue Details.cshtml
, le code passe chaque champ du film aux Helpers HTML DisplayNameFor
et DisplayFor
avec l’objet Model
fortement typé. Les méthodes et les vues Create
et Edit
passent aussi un objet du modèle Movie
.
Examinez la vue Index.cshtml
et la méthode Index
dans le contrôleur Movies. Notez comment le code crée un objet List
quand il appelle la méthode View
. Le code passe cette liste Movies
de la méthode d’action Index
à la vue :
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Lors de la création du contrôleur du film, la génération de modèles automatique a inclus l’instruction @model
suivante en haut du fichier Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
La directive @model
permet d’accéder à la liste des films que le contrôleur a passé à la vue en utilisant un objet Model
qui est fortement typé. Par exemple, dans la vue Index.cshtml
, le code boucle dans les films avec une instruction foreach
sur l’objet Model
fortement typé :
@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>
Comme l’objet Model
est fortement typé en tant qu’objet IEnumerable<Movie>
, chaque élément de la boucle est typé en tant que Movie
. Entre autres avantages, le compilateur valide les types utilisés dans le code.
La configuration de la journalisation est généralement fournie par la section Logging
des fichiers appsettings.{Environment}.json
. Pour journaliser les instructions SQL, ajoutez "Microsoft.EntityFrameworkCore.Database.Command": "Information"
au fichier appsettings.Development.json
:
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MyDB-2;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
,"Microsoft.EntityFrameworkCore.Database.Command": "Information"
}
},
"AllowedHosts": "*"
}
Avec le JSON précédent, les instructions SQL s’affichent dans la ligne de commande et dans la fenêtre de sortie de Visual Studio.
Pour plus d’informations, consultez Journalisation dans .NET Core et ASP.NET Core et ce problème GitHub.
Dans ce tutoriel, des classes sont ajoutées pour la gestion des films dans une base de données. Ces classes constituent la partie « Modèle » de l’application MVC.
Ces classes de modèle sont utilisées avec Entity Framework Core (EF Core) pour utiliser une base de données. EF Core est une infrastructure de mappage relationnel d’objets qui simplifie le code d’accès aux données à écrire.
Les classes du modèle créées sont appelées classes POCO, à partir de Plain Old CLR Objects. Les classes POCO n’ont aucune dépendance vis-à-vis de EF Core. Elles définissent uniquement les propriétés des données qui seront stockées dans la base de données.
Dans ce tutoriel, les classes du modèle sont d’abord créées, puis EF Core crée la base de données.
Cliquez avec le bouton droit sur le dossier Modèles >Ajouter>Classe. Nommez le fichier Movie.cs
.
Mettez à jour le fichier Movie.cs
avec le code suivant :
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; }
}
}
La classe Movie
contient un champ Id
, qui est nécessaire à la base de données pour la clé primaire.
L’attribut DataType de ReleaseDate
spécifie le type de données (Date
). Avec cet attribut :
Les DataAnnotations sont traitées dans un prochain didacticiel.
Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du gestionnaire de package (PMC).
Dans la console du gestionnaire de package, exécutez la commande suivante :
Install-Package Microsoft.EntityFrameworkCore.SqlServer
La commande précédente ajoute le fournisseur EF Core SQL Server. Le package du fournisseur installe le package EF Core en tant que dépendance. Plus loin dans ce tutoriel, d’autres packages sont installés automatiquement lors de l’étape de génération de modèles automatique.
Une classe de contexte de base de données est nécessaire pour coordonner une fonctionnalité EF Core (Créer, Lire, Mettre à jour, Supprimer) pour le modèle Movie
. Le contexte de base de données est dérivé de Microsoft.EntityFrameworkCore.DbContext et il spécifie les entités à inclure dans le modèle de données.
Créez un dossier nommé Data.
Ajoutez un fichier Data/MvcMovieContext.cs
avec le code suivant :
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; }
}
}
Le code précédent crée une propriété DbSet<Movie> pour le jeu d’entités. Dans la terminologie Entity Framework, un jeu d’entités correspond généralement à une table de base de données. Une entité correspond à une ligne dans la table.
ASP.NET Core comprend l’injection de dépendances (DI). Les services (tels que le contexte de base de données EF Core) doivent être inscrits avec l’injection de dépendances au démarrage de l’application. Ces services sont affectés aux composants qui les nécessitent (par exemple les Pages Razor) par le biais de paramètres de constructeur. Le code du constructeur qui obtient une instance de contexte de base de données est indiqué plus loin dans le tutoriel. Dans cette section, vous allez inscrire le contexte de base de données auprès du conteneur d’injection de dépendances.
En tête du Startup.cs
, ajoutez les instructions using
suivantes :
using MvcMovie.Data;
using Microsoft.EntityFrameworkCore;
Ajoutez le code en surbrillance suivant dans Startup.ConfigureServices
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDbContext<MvcMovieContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("MvcMovieContext")));
}
Le nom de la chaîne de connexion est transmis au contexte en appelant une méthode sur un objet DbContextOptions. Pour le développement local, le système de configuration ASP.NET Core lit la chaîne de connexion à partir du fichier appsettings.json
.
Ajoutez une chaîne de connexion au fichier appsettings.json
:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MvcMovieContext": "Server=(localdb)\\mssqllocaldb;Database=MvcMovieContext-1;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
Générez le projet en tant que vérification des erreurs du compilateur.
Utilisez l’outil de génération de modèles automatique pour créer, lire, mettre à jour et supprimer des pages du modèle de film.
Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Contrôleurs, puis choisissez >Ajouter > Nouvel élément généré automatiquement.
Dans la boîte de dialogue Ajouter un modèle automatique, sélectionnez Contrôleur MVC avec vues, utilisant Entity Framework > Ajouter.
Renseignez la boîte de dialogue Ajouter un contrôleur :
Visual Studio crée :
Controllers/MoviesController.cs
)La création automatique de ces fichiers est appelée génération de modèles automatique.
Vous ne pouvez pas encore utiliser les pages générées automatiquement, car la base de données n’existe pas. Si vous exécutez l’application et cliquez sur le lien de l’application Movie, vous obtenez un message d’erreur Impossible d’ouvrir la base de données ou La table suivante n’existe pas.
Utilisez la fonctionnalité EF CoreMigrations pour créer la base de données. La fonctionnalité Migrations est un ensemble d’outils qui vous permettent de créer et de mettre à jour une base de données pour qu’elle corresponde à votre modèle de données.
Dans le menu Outils, sélectionnez Gestionnaire de package NuGet>Console du gestionnaire de package (PMC).
Dans la console du Gestionnaire de package, entrez les commandes suivantes :
Add-Migration InitialCreate
Update-Database
Add-Migration InitialCreate
: Génère un Migrations/{timestamp}_InitialCreate.cs
fichier de migration. L’argument InitialCreate
est le nom de la migration. Vous pouvez utiliser n’importe quel nom, mais par convention, un nom décrivant la migration est sélectionné. Étant donné qu’il s’agit de la première migration, la classe générée contient du code permettant de créer le schéma de la base de données. Le schéma de base de données est basé sur le modèle spécifié dans la classe MvcMovieContext
.
Update-Database
: Met à jour la base de données vers la dernière migration, qui a été créée par la commande précédente. Cette commande exécute la méthode Up
dans le fichier Migrations/{time-stamp}_InitialCreate.cs
, qui crée la base de données.
La commande « database update » génère l’avertissement suivant :
Aucun type n’a été spécifié pour la colonne décimale 'Price' sur le type d’entité 'Movie'. Les valeurs sont tronquées en mode silencieux si elles ne sont pas compatibles avec la précision et l’échelle par défaut. Spécifiez explicitement le type de colonne SQL Server capable d’accueillir toutes les valeurs en utilisant ’HasColumnType()’.
Vous pouvez ignorer cet avertissement, il sera corrigé dans un prochain tutoriel.
Pour plus d’informations sur les outils de la console du gestionnaire de package pour EF Core, consultez EF Core référence sur les outils - Console du gestionnaire de package dans Visual Studio.
Examinez le fichier de migration Migrations/{timestamp}_InitialCreate.cs
:
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Movie",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy",
SqlServerValueGenerationStrategy.IdentityColumn),
Title = table.Column<string>(nullable: true),
ReleaseDate = table.Column<DateTime>(nullable: false),
Genre = table.Column<string>(nullable: true),
Price = table.Column<decimal>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Movie", x => x.Id);
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Movie");
}
}
La méthode Up
crée la table Movie et configure Id
comme la clé primaire. La méthode Down
rétablit les modifications de schéma provoquées par la migration Up
.
Exécutez l’application et cliquez sur le lien Movie App.
Si vous obtenez une exception similaire à celle-ci :
SqlException: Cannot open database "MvcMovieContext-1" requested by the login. The login failed.
Il est probable que vous n’ayez pas effectué l’étape de migration.
Testez la page Create. Entrez et envoyez des données.
Notes
Vous ne pourrez peut-être pas entrer de virgules décimales dans le champ Price
. Pour prendre en charge la validation jQuery pour les paramètres régionaux autres que « Anglais » qui utilisent une virgule (« , ») comme décimale et des formats de date autres que le format « Anglais (États-Unis »), l’application doit être localisée. Pour obtenir des instructions sur la localisation, consultez ce problème GitHub.
Testez les pages Edit, Details et Delete.
Ouvrez le fichier Controllers/MoviesController.cs
et examinez le constructeur :
public class MoviesController : Controller
{
private readonly MvcMovieContext _context;
public MoviesController(MvcMovieContext context)
{
_context = context;
}
Le constructeur utilise une injection de dépendance pour injecter le contexte de base de données (MvcMovieContext
) dans le contrôleur. Le contexte de base de données est utilisé dans chacune des méthodes la CRUD du contrôleur.
Plus tôt dans ce didacticiel, vous avez vu comment un contrôleur peut passer des données ou des objets à une vue en utilisant le dictionnaire ViewData
. Le dictionnaire ViewData
est un objet dynamique qui fournit un moyen pratique d’effectuer une liaison tardive pour passer des informations à une vue.
Le modèle MVC fournit également la possibilité de passer des objets de modèle fortement typés à une vue. Cette approche fortement typée permet de vérifier votre code au moment de la compilation. Le mécanisme de génération de modèles automatique a utilisé cette approche (c’est-à-dire passer un modèle fortement typé) avec la classe MoviesController
et des vues.
Examinez la méthode Details
générée dans le fichier Controllers/MoviesController.cs
:
// GET: Movies/Details/5
public async Task<IActionResult> Details(int? id)
{
if (id == null)
{
return NotFound();
}
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
if (movie == null)
{
return NotFound();
}
return View(movie);
}
Le paramètre id
est généralement passé en tant que données de routage. Par exemple, https://localhost:5001/movies/details/1
définit :
movies
(le premier segment de l’URL).details
(le deuxième segment de l’URL).Vous pouvez aussi passer id
avec une requête de chaîne, comme suit :
https://localhost:5001/movies/details?id=1
Le paramètre id
est défini comme type nullable (int?
) au cas où la valeur d’ID n’est pas fournie.
Une expression lambda est passée à FirstOrDefaultAsync
pour sélectionner les entités de film qui correspondent aux données de routage ou à la valeur de la chaîne de requête.
var movie = await _context.Movie
.FirstOrDefaultAsync(m => m.Id == id);
Si un film est trouvé, une instance du modèle Movie
est passée à la vue Details
:
return View(movie);
Examinez le contenu du fichier Views/Movies/Details.cshtml
:
@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>
L’instruction @model
située en haut du fichier de la vue spécifie le type d’objet attendu par la vue. Lorsque le contrôleur de film était créé, l’instruction @model
suivante était incluse :
@model MvcMovie.Models.Movie
Cette directive @model
autorise l’accès au film que le contrôleur a passé à la vue. L’objet Model
est fortement typé. Par exemple, dans la vue Details.cshtml
, le code passe chaque champ du film aux Helpers HTML DisplayNameFor
et DisplayFor
avec l’objet Model
fortement typé. Les méthodes et les vues Create
et Edit
passent aussi un objet du modèle Movie
.
Examinez la vue Index.cshtml
et la méthode Index
dans le contrôleur Movies. Notez comment le code crée un objet List
quand il appelle la méthode View
. Le code passe cette liste Movies
de la méthode d’action Index
à la vue :
// GET: Movies
public async Task<IActionResult> Index()
{
return View(await _context.Movie.ToListAsync());
}
Lors de la création du contrôleur du film, la génération de modèles automatique a inclus l’instruction @model
suivante en haut du fichier Index.cshtml
:
@model IEnumerable<MvcMovie.Models.Movie>
La directive @model
vous permet d’accéder à la liste des films que le contrôleur a passé à la vue en utilisant un objet Model
qui est fortement typé. Par exemple, dans la vue Index.cshtml
, le code boucle dans les films avec une instruction foreach
sur l’objet Model
fortement typé :
@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>
Comme l’objet Model
est fortement typé (en tant qu’objet IEnumerable<Movie>
), chaque élément de la boucle est typé en tant que Movie
. Entre autres avantages, cela signifie que votre code est vérifié au moment de la compilation :
Commentaires sur ASP.NET Core
ASP.NET Core est un projet open source. Sélectionnez un lien pour fournir des commentaires :
Événements
31 mars, 23 h - 2 avr., 23 h
L’événement de la communauté Microsoft Fabric, Power BI, SQL et AI ultime. 31 mars au 2 avril 2025.
Inscrivez-vous aujourd’huiEntrainement
Module
Créer une interface utilisateur web avec ASP.NET Core - Training
Apprenez à créer des pages web en utilisant Razor avec ASP.NET Core.