Pages Razor avec Entity Framework Core dans ASP.NET Core - Tutoriel 1 sur 8Razor Pages with Entity Framework Core in ASP.NET Core - Tutorial 1 of 8

Par Tom Dykstra et Rick AndersonBy Tom Dykstra and Rick Anderson

L’exemple d’application web Contoso University montre comment créer une application web Razor Pages ASP.NET Core à l’aide d’Entity Framework (EF) Core.The Contoso University sample web app demonstrates how to create an ASP.NET Core Razor Pages app using Entity Framework (EF) Core.

L’exemple d’application est un site web pour une université Contoso fictive.The sample app is a web site for a fictional Contoso University. Il comprend des fonctionnalités telles que l’admission des étudiants, la création des cours et les affectations des formateurs.It includes functionality such as student admission, course creation, and instructor assignments. Cette page est la première d’une série de didacticiels qui expliquent comment générer l’exemple d’application Contoso University.This page is the first in a series of tutorials that explain how to build the Contoso University sample app.

Télécharger ou afficher l’application complète.Download or view the completed app. Télécharger les instructions.Download instructions.

PrérequisPrerequisites

Visual Studio 2017 version 15.7.3 ou ultérieure avec les charges de travail suivantes :Visual Studio 2017 version 15.7.3 or later with the following workloads:

  • Développement web et ASP.NETASP.NET and web development
  • Développement multiplateforme .NET Core.NET Core cross-platform development

Connaissance des Pages Razor.Familiarity with Razor Pages. Les programmeurs débutants doivent lire Bien démarrer avec les pages Razor avant de démarrer cette série.New programmers should complete Get started with Razor Pages before starting this series.

Résolution des problèmesTroubleshooting

Si vous rencontrez un problème que vous ne pouvez pas résoudre, vous pouvez généralement trouver la solution en comparant votre code au projet terminé.If you run into a problem you can't resolve, you can generally find the solution by comparing your code to the completed project. Un bon moyen d’obtenir de l’aide est de publier une question sur StackOverflow.com pour ASP.NET Core ou EF Core.A good way to get help is by posting a question to StackOverflow.com for ASP.NET Core or EF Core.

L’application web Contoso UniversityThe Contoso University web app

L’application générée dans ces didacticiels est le site web de base d’une université.The app built in these tutorials is a basic university web site.

Les utilisateurs peuvent afficher et mettre à jour les informations relatives aux étudiants, aux cours et aux formateurs.Users can view and update student, course, and instructor information. Voici quelques-uns des écrans créés dans le didacticiel.Here are a few of the screens created in the tutorial.

Page d’index des étudiants

Page de modification des étudiants

Le style de l’interface utilisateur de ce site est proche de ce qui est généré par les modèles prédéfinis.The UI style of this site is close to what's generated by the built-in templates. Le didacticiel est axé sur Core EF avec des pages Razor, et non sur l’interface utilisateur.The tutorial focus is on EF Core with Razor Pages, not the UI.

Créer l’application web Razor Pages ContosoUniversityCreate the ContosoUniversity Razor Pages web app

  • Dans Visual Studio, dans le menu Fichier, sélectionnez Nouveau > Projet.From the Visual Studio File menu, select New > Project.
  • Créez une application web ASP.NET Core.Create a new ASP.NET Core Web Application. Nommez le projet ContosoUniversity.Name the project ContosoUniversity. Il est important de nommer le projet ContosoUniversity afin que les espaces de noms correspondent quand le code est copié/collé.It's important to name the project ContosoUniversity so the namespaces match when code is copy/pasted.
  • Sélectionnez ASP.NET Core 2.1 dans la liste déroulante, puis sélectionnez Application web.Select ASP.NET Core 2.1 in the dropdown, and then select Web Application.

Pour les images des étapes précédentes, consultez Créer une application web Razor.For images of the preceding steps, see Create a Razor web app. Exécutez l’application.Run the app.

Configurer le style du siteSet up the site style

Quelques changements permettent de définir le menu, la disposition et la page d’accueil du site.A few changes set up the site menu, layout, and home page. Mettez à jour Pages/Shared/_Layout.cshtml avec les changements suivants :Update Pages/Shared/_Layout.cshtml with the following changes:

  • Remplacez chaque occurrence de « ContosoUniversity » par « Contoso University ».Change each occurrence of "ContosoUniversity" to "Contoso University". Il y a trois occurrences.There are three occurrences.

  • Ajoutez des entrées de menu pour Students, Courses, Instructors et Departments, et supprimez l’entrée de menu Contact.Add menu entries for Students, Courses, Instructors, and Departments, and delete the Contact menu entry.

Les modifications sont mises en surbrillance.The changes are highlighted. (Tout le balisage n’est pas affiché.)(All the markup is not displayed.)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] : Contoso University</title>

    <environment include="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
        <link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
    </environment>
</head>
<body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a asp-page="/Index" class="navbar-brand">Contoso University</a>
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a asp-page="/Index">Home</a></li>
                    <li><a asp-page="/About">About</a></li>
                    <li><a asp-page="/Students/Index">Students</a></li>
                    <li><a asp-page="/Courses/Index">Courses</a></li>
                    <li><a asp-page="/Instructors/Index">Instructors</a></li>
                    <li><a asp-page="/Departments/Index">Departments</a></li>
                </ul>
            </div>
        </div>
    </nav>

    <partial name="_CookieConsentPartial" />

    <div class="container body-content">
        @RenderBody()
        <hr />
        <footer>
            <p>&copy; 2018 : Contoso University</p>
        </footer>
    </div>

    @*Remaining markup not shown for brevity.*@

Dans Pages/Index.cshtml, remplacez le contenu du fichier par le code suivant afin de remplacer le texte sur ASP.NET et MVC par le texte concernant cette application :In Pages/Index.cshtml, replace the contents of the file with the following code to replace the text about ASP.NET and MVC with text about this app:

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

<div class="jumbotron">
    <h1>Contoso University</h1>
</div>
<div class="row">
    <div class="col-md-4">
        <h2>Welcome to Contoso University</h2>
        <p>
            Contoso University is a sample application that
            demonstrates how to use Entity Framework Core in an
            ASP.NET Core Razor Pages web app.
        </p>
    </div>
    <div class="col-md-4">
        <h2>Build it from scratch</h2>
        <p>You can build the application by following the steps in a series of tutorials.</p>
        <p>
            <a class="btn btn-default"
               href="https://docs.microsoft.com/aspnet/core/data/ef-rp/intro">
                See the tutorial &raquo;
            </a>
        </p>
    </div>
    <div class="col-md-4">
        <h2>Download it</h2>
        <p>You can download the completed project from GitHub.</p>
        <p>
            <a class="btn btn-default"
               href="https://github.com/aspnet/AspNetCore.Docs/tree/master/aspnetcore/data/ef-rp/intro/samples/cu-final">
                See project source code &raquo;
            </a>
        </p>
    </div>
</div>

Créer le modèle de donnéesCreate the data model

Créez des classes d’entités pour l’application Contoso University.Create entity classes for the Contoso University app. Commencez par les trois entités suivantes :Start with the following three entities:

Diagramme de modèle de données Cours-Inscription-Étudiant

Il existe une relation un-à-plusieurs entre les entités Student et Enrollment.There's a one-to-many relationship between Student and Enrollment entities. Il existe une relation un-à-plusieurs entre les entités Course et Enrollment.There's a one-to-many relationship between Course and Enrollment entities. Un étudiant peut s’inscrire à autant de cours qu’il le souhaite.A student can enroll in any number of courses. Un cours peut avoir une quantité illimitée d’élèves inscrits.A course can have any number of students enrolled in it.

Dans les sections suivantes, une classe pour chacune de ces entités est créée.In the following sections, a class for each one of these entities is created.

L’entité StudentThe Student entity

Diagramme de l’entité Student

Créez un dossier Models.Create a Models folder. Dans le dossier Models, créez un fichier de classe nommé Student.cs avec le code suivant :In the Models folder, create a class file named Student.cs with the following code:

using System;
using System.Collections.Generic;

namespace ContosoUniversity.Models
{
    public class Student
    {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }
}

La propriété ID devient la colonne de clé primaire de la table de base de données qui correspond à cette classe.The ID property becomes the primary key column of the database (DB) table that corresponds to this class. Par défaut, EF Core interprète une propriété nommée ID ou classnameID comme clé primaire.By default, EF Core interprets a property that's named ID or classnameID as the primary key. Dans classnameID, classname est le nom de la classe.In classnameID, classname is the name of the class. L’autre clé primaire reconnue automatiquement est StudentID dans l’exemple précédent.The alternative automatically recognized primary key is StudentID in the preceding example.

La propriété Enrollments est une propriété de navigation.The Enrollments property is a navigation property. Les propriétés de navigation établissent des liaisons à d’autres entités qui sont associées à cette entité.Navigation properties link to other entities that are related to this entity. Ici, la propriété Enrollments d’un Student entity contient toutes les entités Enrollment associées à ce Student.In this case, the Enrollments property of a Student entity holds all of the Enrollment entities that are related to that Student. Par exemple, si une ligne Student dans la base de données a deux lignes Enrollment associées, la propriété de navigation Enrollments contient ces deux entités Enrollment.For example, if a Student row in the DB has two related Enrollment rows, the Enrollments navigation property contains those two Enrollment entities. Une ligne Enrollment associée est une ligne qui contient la valeur de clé primaire de cette étudiant dans la colonne StudentID.A related Enrollment row is a row that contains that student's primary key value in the StudentID column. Par exemple, supposez que l’étudiant avec ID=1 a deux lignes dans la table Enrollment.For example, suppose the student with ID=1 has two rows in the Enrollment table. La table Enrollment a deux lignes avec StudentID = 1.The Enrollment table has two rows with StudentID = 1. StudentID est une clé étrangère dans la table Enrollment qui spécifie l’étudiant dans la table Student.StudentID is a foreign key in the Enrollment table that specifies the student in the Student table.

Si une propriété de navigation peut contenir plusieurs entités, la propriété de navigation doit être un type de liste, tel que ICollection<T>.If a navigation property can hold multiple entities, the navigation property must be a list type, such as ICollection<T>. Vous pouvez spécifier ICollection<T>, ou un type tel que List<T> ou HashSet<T>.ICollection<T> can be specified, or a type such as List<T> or HashSet<T>. Quand vous utilisez ICollection<T>, EF Core crée une collection HashSet<T> par défaut.When ICollection<T> is used, EF Core creates a HashSet<T> collection by default. Les propriétés de navigation qui contiennent plusieurs entités proviennent de relations plusieurs-à-plusieurs et un-à-plusieurs.Navigation properties that hold multiple entities come from many-to-many and one-to-many relationships.

L’entité EnrollmentThe Enrollment entity

Diagramme de l’entité Enrollment

Dans le dossier Models, créez un fichier Enrollment.cs avec le code suivant :In the Models folder, create Enrollment.cs with the following code:

namespace ContosoUniversity.Models
{
    public enum Grade
    {
        A, B, C, D, F
    }

    public class Enrollment
    {
        public int EnrollmentID { get; set; }
        public int CourseID { get; set; }
        public int StudentID { get; set; }
        public Grade? Grade { get; set; }

        public Course Course { get; set; }
        public Student Student { get; set; }
    }
}

La propriété EnrollmentID est la clé primaire.The EnrollmentID property is the primary key. Cette entité utilise le modèle classnameID au lieu de ID comme l’entité Student.This entity uses the classnameID pattern instead of ID like the Student entity. En général, les développeurs choisissent un modèle et l’utilisent dans tout le modèle de données.Typically developers choose one pattern and use it throughout the data model. Dans un prochain didacticiel, nous verrons qu’utiliser ID sans classname simplifie l’implémentation de l’héritage dans le modèle de données.In a later tutorial, using ID without classname is shown to make it easier to implement inheritance in the data model.

La propriété Grade est un enum.The Grade property is an enum. Le point d’interrogation après la déclaration de type Grade indique que la propriété Grade est nullable.The question mark after the Grade type declaration indicates that the Grade property is nullable. Une note (Grade) qui a la valeur Null est différente d’une note égale à zéro : la valeur Null signifie qu’une note n’est pas connue ou n’a pas encore été affectée.A grade that's null is different from a zero grade -- null means a grade isn't known or hasn't been assigned yet.

La propriété StudentID est une clé étrangère, et la propriété de navigation correspondante est Student.The StudentID property is a foreign key, and the corresponding navigation property is Student. Une entité Enrollment est associée à une entité Student. Par conséquent, la propriété contient une seule entité Student.An Enrollment entity is associated with one Student entity, so the property contains a single Student entity. L’entité Student diffère de la propriété de navigation Student.Enrollments, qui contient plusieurs entités Enrollment.The Student entity differs from the Student.Enrollments navigation property, which contains multiple Enrollment entities.

La propriété CourseID est une clé étrangère, et la propriété de navigation correspondante est Course.The CourseID property is a foreign key, and the corresponding navigation property is Course. Une entité Enrollment est associée à une entité Course.An Enrollment entity is associated with one Course entity.

EF Core interprète une propriété en tant que clé étrangère si elle se nomme <navigation property name><primary key property name>.EF Core interprets a property as a foreign key if it's named <navigation property name><primary key property name>. Par exemple, StudentID pour la propriété de navigation Student, puisque la clé primaire de l’entité Student est ID.For example,StudentID for the Student navigation property, since the Student entity's primary key is ID. Les propriétés de clé étrangère peuvent également se nommer <primary key property name>.Foreign key properties can also be named <primary key property name>. Par exemple, CourseID puisque la clé primaire de l’entité Course est CourseID.For example, CourseID since the Course entity's primary key is CourseID.

L’entité CourseThe Course entity

Diagramme de l’entité Course

Dans le dossier Models, créez un fichier Course.cs avec le code suivant :In the Models folder, create Course.cs with the following code:

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models
{
    public class Course
    {
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }

        public ICollection<Enrollment> Enrollments { get; set; }
    }
}

La propriété Enrollments est une propriété de navigation.The Enrollments property is a navigation property. Une entité Course peut être associée à un nombre quelconque d’entités Enrollment.A Course entity can be related to any number of Enrollment entities.

L’attribut DatabaseGenerated permet à l’application de spécifier la clé primaire, plutôt que de la faire générer par la base de données.The DatabaseGenerated attribute allows the app to specify the primary key rather than having the DB generate it.

Générer automatiquement le modèle d’étudiantScaffold the student model

Dans cette section, le modèle d’étudiant est généré automatiquement.In this section, the student model is scaffolded. Autrement dit, l’outil de génération de modèles automatique génère des pages pour les opérations de création (Create), de lecture (Read), de mise à jour (Update) et de suppression (Delete) (CRUD) pour le modèle d’étudiant.That is, the scaffolding tool produces pages for Create, Read, Update, and Delete (CRUD) operations for the student model.

  • Générez le projet.Build the project.
  • Créez le dossier Pages/Students.Create the Pages/Students folder.
  • Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Pages/Students > Ajouter > Nouvel élément généré automatiquement.In Solution Explorer, right click on the Pages/Students folder > Add > New Scaffolded Item.
  • Dans la boîte de dialogue Ajouter un modèle automatique, sélectionnez Pages Razor avec Entity Framework (CRUD) > Ajouter.In the Add Scaffold dialog, select Razor Pages using Entity Framework (CRUD) > ADD.

Renseignez la boîte de dialogue Pages Razor avec Entity Framework (CRUD) :Complete the Add Razor Pages using Entity Framework (CRUD) dialog:

  • Dans la liste déroulante Classe de modèle, sélectionnez Student (ContosoUniversity.Models).In the Model class drop-down, select Student (ContosoUniversity.Models).
  • Dans la ligne Classe de contexte de données, sélectionnez le signe + (plus) et remplacez le nom généré par ContosoUniversity.Models.SchoolContext.In the Data context class row, select the + (plus) sign and change the generated name to ContosoUniversity.Models.SchoolContext.
  • Dans la liste déroulante Classe de contexte de données, sélectionnez ContosoUniversity.Models.SchoolContextIn the Data context class drop-down, select ContosoUniversity.Models.SchoolContext
  • Sélectionnez Ajouter.Select Add.

Boîte de dialogue CRUD

Consultez Générer automatiquement le modèle de film si vous rencontrez un problème à l’étape précédente.See Scaffold the movie model if you have a problem with the preceding step.

Le processus de génération de modèles automatique a créé et changé les fichiers suivants :The scaffold process created and changed the following files:

Fichiers créésFiles created

  • Pages/Students Create, Delete, Details, Edit, Index.Pages/Students Create, Delete, Details, Edit, Index.
  • Data/SchoolContext.csData/SchoolContext.cs

Mises à jour du fichierFile updates

  • Startup.cs : Les changements apportés à ce fichier sont détaillés dans la section suivante.Startup.cs : Changes to this file are detailed in the next section.
  • appsettings.json : La chaîne de connexion utilisée pour se connecter à une base de données locale est ajoutée.appsettings.json : The connection string used to connect to a local database is added.

Examiner le contexte inscrit avec l’injection de dépendancesExamine the context registered with dependency injection

ASP.NET Core comprend l’injection de dépendances.ASP.NET Core is built with dependency injection. Des services (tels que le contexte de base de données EF Core) sont inscrits avec l’injection de dépendances au démarrage de l’application.Services (such as the EF Core DB context) are registered with dependency injection during application startup. Ces services sont affectés aux composants qui les nécessitent (par exemple les Pages Razor) par le biais de paramètres de constructeur.Components that require these services (such as Razor Pages) are provided these services via constructor parameters. Le code du constructeur qui obtient une instance de contexte de base de données est indiqué plus loin dans le didacticiel.The constructor code that gets a db context instance is shown later in the tutorial.

L’outil de génération de modèles automatique a créé automatiquement un contexte de base de données et l’a inscrit dans le conteneur d’injection de dépendances.The scaffolding tool automatically created a DB Context and registered it with the dependency injection container.

Examinez la méthode ConfigureServices dans Startup.cs.Examine the ConfigureServices method in Startup.cs. La ligne en surbrillance a été ajoutée par l’outil de génération de modèles automatique :The highlighted line was added by the scaffolder:

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

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

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

Le nom de la chaîne de connexion est transmis au contexte en appelant une méthode sur un objet DbContextOptions.The name of the connection string is passed in to the context by calling a method on a DbContextOptions object. Pour le développement local, le système de configuration ASP.NET Core lit la chaîne de connexion à partir du fichier appsettings.json.For local development, the ASP.NET Core configuration system reads the connection string from the appsettings.json file.

Mettre à jour la méthode MainUpdate main

Dans Program.cs, modifiez la méthode Main pour effectuer les opérations suivantes :In Program.cs, modify the Main method to do the following:

  • Obtenir une instance de contexte de base de données à partir du conteneur d’injection de dépendances.Get a DB context instance from the dependency injection container.
  • Appelez EnsureCreated.Call the EnsureCreated.
  • Supprimez le contexte une fois la méthode EnsureCreated exécutée.Dispose the context when the EnsureCreated method completes.

Le code suivant montre le fichier Program.cs mis à jour.The following code shows the updated Program.cs file.

using ContosoUniversity.Models;                   // SchoolContext
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;   // CreateScope
using Microsoft.Extensions.Logging;
using System;

namespace ContosoUniversity
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var host = CreateWebHostBuilder(args).Build();

            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;

                try
                {
                    var context = services.GetRequiredService<SchoolContext>();
                    context.Database.EnsureCreated();
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred creating the DB.");
                }
            }

            host.Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

EnsureCreated garantit que la base de données existe pour le contexte.EnsureCreated ensures that the database for the context exists. Si elle existe, aucune action n’est effectuée.If it exists, no action is taken. Si elle n’existe pas, la base de données et tous ses schéma sont créés.If it does not exist, then the database and all its schema are created. EnsureCreated n’utilise pas de migrations pour créer la base de données.EnsureCreated does not use migrations to create the database. Une base de données créée avec EnsureCreated ne peut pas être mise à jour à l’aide de migrations par la suite.A database that is created with EnsureCreated cannot be later updated using migrations.

EnsureCreated est appelée au démarrage de l’application, ce qui active le flux de travail suivant :EnsureCreated is called on app start, which allows the following work flow:

  • Supprimez la base de données.Delete the DB.
  • Modification du schéma de base de données (par exemple, ajout d’un champ EmailAddress).Change the DB schema (for example, add an EmailAddress field).
  • Exécutez l’application.Run the app.
  • EnsureCreated crée une base de données avec la colonne EmailAddress.EnsureCreated creates a DB with theEmailAddress column.

EnsureCreated est pratique au début du développement quand le schéma évolue rapidement.EnsureCreated is convenient early in development when the schema is rapidly evolving. Plus loin dans le tutoriel, la base de données est supprimée et les migrations sont utilisées.Later in the tutorial the DB is deleted and migrations are used.

Tester l’applicationTest the app

Exécutez l’application et acceptez la politique de cookies.Run the app and accept the cookie policy. Cette application ne conserve pas les informations personnelles.This app doesn't keep personal information. Vous pouvez en savoir plus sur la politique de cookies à la section Prise en charge du règlement général sur la protection des données (RGPD).You can read about the cookie policy at EU General Data Protection Regulation (GDPR) support.

  • Sélectionnez le lien Students, puis Créer nouveau.Select the Students link and then Create New.
  • Testez les liens Edit, Details et Delete.Test the Edit, Details, and Delete links.

Examiner le contexte de base de données SchoolContextExamine the SchoolContext DB context

La classe principale qui coordonne les fonctionnalités d’EF Core pour un modèle de données spécifié est la classe de contexte de base de données.The main class that coordinates EF Core functionality for a given data model is the DB context class. Le contexte de données est dérivé de Microsoft.EntityFrameworkCore.DbContext.The data context is derived from Microsoft.EntityFrameworkCore.DbContext. Il spécifie les entités qui sont incluses dans le modèle de données.The data context specifies which entities are included in the data model. Dans ce projet, la classe est nommée SchoolContext.In this project, the class is named SchoolContext.

Mettez à jour SchoolContext.cs avec le code suivant :Update SchoolContext.cs with the following code:

using Microsoft.EntityFrameworkCore;

namespace ContosoUniversity.Models
{
    public class SchoolContext : DbContext
    {
        public SchoolContext(DbContextOptions<SchoolContext> options)
            : base(options)
        {
        }

        public DbSet<Student> Student { get; set; }
        public DbSet<Enrollment> Enrollment { get; set; }
        public DbSet<Course> Course { get; set; }
    }
}

Le code en surbrillance crée une propriété DbSet<TEntity> pour chaque jeu d’entités.The highlighted code creates a DbSet<TEntity> property for each entity set. Dans la terminologie d’EF Core :In EF Core terminology:

  • Un jeu d’entités correspond généralement à une table de base de données.An entity set typically corresponds to a DB table.
  • Une entité correspond à une ligne dans la table.An entity corresponds to a row in the table.

DbSet<Enrollment> et DbSet<Course> peuvent être omis.DbSet<Enrollment> and DbSet<Course> could be omitted. EF Core les inclut implicitement, car l’entité Student référence l’entité Enrollment, et l’entité Enrollment référence l’entité Course.EF Core includes them implicitly because the Student entity references the Enrollment entity, and the Enrollment entity references the Course entity. Pour ce didacticiel, conservez DbSet<Enrollment> et DbSet<Course> dans le SchoolContext.For this tutorial, keep DbSet<Enrollment> and DbSet<Course> in the SchoolContext.

SQL Server Express LocalDBSQL Server Express LocalDB

La chaîne de connexion spécifie SQL Server LocalDB.The connection string specifies SQL Server LocalDB. LocalDB est une version allégée du moteur de base de données SQL Server Express. Elle est destinée au développement d’applications, et non à une utilisation en production.LocalDB is a lightweight version of the SQL Server Express Database Engine and is intended for app development, not production use. LocalDB démarre à la demande et s’exécute en mode utilisateur, ce qui n’implique aucune configuration complexe.LocalDB starts on demand and runs in user mode, so there's no complex configuration. Par défaut, LocalDB crée des fichiers de base de données .mdf dans le répertoire C:/Users/<user>.By default, LocalDB creates .mdf DB files in the C:/Users/<user> directory.

Ajouter du code pour initialiser la base de données avec des données de testAdd code to initialize the DB with test data

EF Core crée une base de données vide.EF Core creates an empty DB. Dans cette section, une méthode Initialize est écrite pour la remplir avec des données de test.In this section, an Initialize method is written to populate it with test data.

Dans le dossier Data, créez un fichier de classe nommé DbInitializer.cs et ajoutez le code suivant :In the Data folder, create a new class file named DbInitializer.cs and add the following code:

using ContosoUniversity.Models;
using System;
using System.Linq;

namespace ContosoUniversity.Models
{
    public static class DbInitializer
    {
        public static void Initialize(SchoolContext context)
        {
            // context.Database.EnsureCreated();

            // Look for any students.
            if (context.Student.Any())
            {
                return;   // DB has been seeded
            }

            var students = new Student[]
            {
            new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2005-09-01")},
            new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2003-09-01")},
            new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2002-09-01")},
            new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2001-09-01")},
            new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2003-09-01")},
            new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2005-09-01")}
            };
            foreach (Student s in students)
            {
                context.Student.Add(s);
            }
            context.SaveChanges();

            var courses = new Course[]
            {
            new Course{CourseID=1050,Title="Chemistry",Credits=3},
            new Course{CourseID=4022,Title="Microeconomics",Credits=3},
            new Course{CourseID=4041,Title="Macroeconomics",Credits=3},
            new Course{CourseID=1045,Title="Calculus",Credits=4},
            new Course{CourseID=3141,Title="Trigonometry",Credits=4},
            new Course{CourseID=2021,Title="Composition",Credits=3},
            new Course{CourseID=2042,Title="Literature",Credits=4}
            };
            foreach (Course c in courses)
            {
                context.Course.Add(c);
            }
            context.SaveChanges();

            var enrollments = new Enrollment[]
            {
            new Enrollment{StudentID=1,CourseID=1050,Grade=Grade.A},
            new Enrollment{StudentID=1,CourseID=4022,Grade=Grade.C},
            new Enrollment{StudentID=1,CourseID=4041,Grade=Grade.B},
            new Enrollment{StudentID=2,CourseID=1045,Grade=Grade.B},
            new Enrollment{StudentID=2,CourseID=3141,Grade=Grade.F},
            new Enrollment{StudentID=2,CourseID=2021,Grade=Grade.F},
            new Enrollment{StudentID=3,CourseID=1050},
            new Enrollment{StudentID=4,CourseID=1050},
            new Enrollment{StudentID=4,CourseID=4022,Grade=Grade.F},
            new Enrollment{StudentID=5,CourseID=4041,Grade=Grade.C},
            new Enrollment{StudentID=6,CourseID=1045},
            new Enrollment{StudentID=7,CourseID=3141,Grade=Grade.A},
            };
            foreach (Enrollment e in enrollments)
            {
                context.Enrollment.Add(e);
            }
            context.SaveChanges();
        }
    }
}

Remarque : Le code précédent utilise Models pour l’espace de noms (namespace ContosoUniversity.Models) au lieu de Data.Note: The preceding code uses Models for the namespace (namespace ContosoUniversity.Models) rather than Data. Models est cohérent avec le code généré par l’outil de génération de modèles automatique.Models is consistent with the scaffolder-generated code. Pour plus d’informations, consultez ce problème de génération de modèles automatique GitHub.For more information, see this GitHub scaffolding issue.

Le code vérifie s’il existe des étudiants dans la base de données.The code checks if there are any students in the DB. S’il n’y en a pas, la base de données est initialisée avec des données de test.If there are no students in the DB, the DB is initialized with test data. Il charge les données de test dans les tableaux plutôt que dans les collections List<T> afin d’optimiser les performances.It loads test data into arrays rather than List<T> collections to optimize performance.

La méthode EnsureCreated crée automatiquement la base de données pour le contexte de base de données.The EnsureCreated method automatically creates the DB for the DB context. Si la base de données existe, EnsureCreated retourne sans modifier la base de données.If the DB exists, EnsureCreated returns without modifying the DB.

Dans Program.cs, modifiez la méthode Main pour appeler Initialize :In Program.cs, modify the Main method to call Initialize:

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<SchoolContext>();
                // using ContosoUniversity.Data; 
                DbInitializer.Initialize(context);
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred creating the DB.");
            }
        }

        host.Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>();
}

Supprimez les enregistrements d’étudiants et redémarrez l’application.Delete any student records and restart the app. Si la base de données n’est pas initialisée, définissez un point d’arrêt dans Initialize pour diagnostiquer le problème.If the DB is not initialized, set a break point in Initialize to diagnose the problem.

Afficher la base de donnéesView the DB

Le nom de la base de données est généré à partir du nom de contexte indiqué précédemment, ainsi que d’un tiret et d’un GUID.The database name is generated from the context name you provided earlier plus a dash and a GUID. Il sera donc « SchoolContext-{GUID} ».Thus, the database name will be "SchoolContext-{GUID}". Le GUID est différent pour chaque utilisateur.The GUID will be different for each user. Ouvrez l’Explorateur d’objets SQL Server (SSOX) à partir du menu Affichage de Visual Studio.Open SQL Server Object Explorer (SSOX) from the View menu in Visual Studio. Dans SSOX, cliquez sur (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID}.In SSOX, click (localdb)\MSSQLLocalDB > Databases > SchoolContext-{GUID}.

Développez le nœud Tables.Expand the Tables node.

Cliquez avec le bouton droit sur la table Student et cliquez sur Afficher les données pour voir les colonnes créées et les lignes insérées dans la table.Right-click the Student table and click View Data to see the columns created and the rows inserted into the table.

Code asynchroneAsynchronous code

La programmation asynchrone est le mode par défaut pour ASP.NET Core et EF Core.Asynchronous programming is the default mode for ASP.NET Core and EF Core.

Un serveur web a un nombre limité de threads disponibles et, dans les situations de forte charge, tous les threads disponibles peuvent être utilisés.A web server has a limited number of threads available, and in high load situations all of the available threads might be in use. Quand cela se produit, le serveur ne peut pas traiter de nouvelle requête tant que les threads ne sont pas libérés.When that happens, the server can't process new requests until the threads are freed up. Avec le code synchrone, plusieurs threads peuvent être bloqués alors qu’ils n’effectuent en fait aucun travail, car ils attendent que des E/S se terminent.With synchronous code, many threads may be tied up while they aren't actually doing any work because they're waiting for I/O to complete. Avec le code asynchrone, quand un processus attend que des E/S se terminent, son thread est libéré afin d’être utilisé par le serveur pour traiter d’autres demandes.With asynchronous code, when a process is waiting for I/O to complete, its thread is freed up for the server to use for processing other requests. Il permet ainsi d’utiliser les ressources serveur plus efficacement, et le serveur peut gérer plus de trafic sans retard.As a result, asynchronous code enables server resources to be used more efficiently, and the server is enabled to handle more traffic without delays.

Le code asynchrone introduit néanmoins une petite surcharge au moment de l’exécution.Asynchronous code does introduce a small amount of overhead at run time. Dans les situations de faible trafic, le gain de performances est négligeable, tandis qu’en cas de trafic élevé l’amélioration potentielle des performances est importante.For low traffic situations, the performance hit is negligible, while for high traffic situations, the potential performance improvement is substantial.

Dans le code suivant, le mot clé async, la valeur renvoyée Task<T>, le mot clé await et la méthode ToListAsync déclenchent l’exécution asynchrone du code.In the following code, the async keyword, Task<T> return value, await keyword, and ToListAsync method make the code execute asynchronously.

public async Task OnGetAsync()
{
    Student = await _context.Student.ToListAsync();
}
  • Le mot clé async fait en sorte que le compilateur :The async keyword tells the compiler to:

    • Génère des rappels pour les parties du corps de méthode.Generate callbacks for parts of the method body.
    • Crée automatiquement l’objet Task qui est retourné.Automatically create the Task object that's returned. Pour plus d’informations, consultez Type de retour Task.For more information, see Task Return Type.
  • Le type de retour implicite Task représente le travail en cours.The implicit return type Task represents ongoing work.

  • Le mot clé await fait en sorte que le compilateur fractionne la méthode en deux parties.The await keyword causes the compiler to split the method into two parts. La première partie se termine par l’opération qui est démarrée de façon asynchrone.The first part ends with the operation that's started asynchronously. La seconde partie est placée dans une méthode de rappel qui est appelée quand l’opération se termine.The second part is put into a callback method that's called when the operation completes.

  • ToListAsync est la version asynchrone de la méthode d’extension ToList.ToListAsync is the asynchronous version of the ToList extension method.

Voici quelques éléments à connaître lors de l’écriture de code asynchrone qui utilise EF Core :Some things to be aware of when writing asynchronous code that uses EF Core:

  • Seules les instructions qui provoquent l’envoi de requêtes ou de commandes vers la base de données sont exécutées de façon asynchrone.Only statements that cause queries or commands to be sent to the DB are executed asynchronously. Cela comprend ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsync et SaveChangesAsync,That includes, ToListAsync, SingleOrDefaultAsync, FirstOrDefaultAsync, and SaveChangesAsync. mais pas les instructions qui ne font que changer un IQueryable, telles que var students = context.Students.Where(s => s.LastName == "Davolio").It doesn't include statements that just change an IQueryable, such as var students = context.Students.Where(s => s.LastName == "Davolio").
  • Un contexte EF Core n’est pas thread-safe : n’essayez pas d’effectuer plusieurs opérations en parallèle.An EF Core context isn't thread safe: don't try to do multiple operations in parallel.
  • Pour tirer parti des avantages de performances du code asynchrone, vérifiez que les packages de bibliothèque (par exemple pour la pagination) utilisent le mode asynchrone s’ils appellent des méthodes EF Core qui envoient des requêtes à la base de données.To take advantage of the performance benefits of async code, verify that library packages (such as for paging) use async if they call EF Core methods that send queries to the DB.

Pour plus d’informations sur la programmation asynchrone dans .NET, consultez Vue d’ensemble d’Async et Programmation asynchrone avec async et await.For more information about asynchronous programming in .NET, see Async Overview and Asynchronous programming with async and await.

Dans le didacticiel suivant, nous allons examiner les opérations CRUD de base (créer, lire, mettre à jour, supprimer).In the next tutorial, basic CRUD (create, read, update, delete) operations are examined.

Ressources supplémentairesAdditional resources