Tutoriel : En savoir plus sur les scénarios avancés - ASP.NET MVC avec EF CoreTutorial: Learn about advanced scenarios - ASP.NET MVC with EF Core

Dans le didacticiel précédent, vous avez implémenté l’héritage TPH (table par hiérarchie).In the previous tutorial, you implemented table-per-hierarchy inheritance. Ce didacticiel présente plusieurs rubriques qu’il est utile de connaître lorsque vous allez au-delà des principes de base du développement d’applications web ASP.NET Core qui utilisent Entity Framework Core.This tutorial introduces several topics that are useful to be aware of when you go beyond the basics of developing ASP.NET Core web applications that use Entity Framework Core.

Dans ce didacticiel, vous avez effectué les actions suivantes :In this tutorial, you:

  • Exécuter des requêtes SQL brutesPerform raw SQL queries
  • Appeler une requête pour retourner des entitésCall a query to return entities
  • Appeler une requête pour retourner d’autres typesCall a query to return other types
  • Appeler une requête de mise à jourCall an update query
  • Examiner les requêtes SQLExamine SQL queries
  • Créer une couche d’abstractionCreate an abstraction layer
  • En savoir plus sur la Détection automatique des modificationsLearn about Automatic change detection
  • En savoir plus sur le code source et les plans de développement EF CoreLearn about EF Core source code and development plans
  • Apprendre à utiliser du code dynamique LINQ pour simplifier le codeLearn how to use dynamic LINQ to simplify code

PrérequisPrerequisites

Exécuter des requêtes SQL brutesPerform raw SQL queries

L’un des avantages d’utiliser Entity Framework est que cela évite de lier votre code trop étroitement à une méthode particulière de stockage des données.One of the advantages of using the Entity Framework is that it avoids tying your code too closely to a particular method of storing data. Il le fait en générant des requêtes et des commandes SQL pour vous, ce qui vous évite d’avoir à les écrire vous-même.It does this by generating SQL queries and commands for you, which also frees you from having to write them yourself. Mais, dans certains scénarios exceptionnels, vous devez exécuter des requêtes SQL spécifiques que vous créez manuellement.But there are exceptional scenarios when you need to run specific SQL queries that you have manually created. Pour ces scénarios, l’API Entity Framework Code First comprend des méthodes qui vous permettent de transmettre des commandes SQL directement à la base de données.For these scenarios, the Entity Framework Code First API includes methods that enable you to pass SQL commands directly to the database. Les options suivantes sont disponibles dans EF Core 1.0 :You have the following options in EF Core 1.0:

  • Utilisez la méthode DbSet.FromSql pour les requêtes qui renvoient des types d’entités.Use the DbSet.FromSql method for queries that return entity types. Les objets renvoyés doivent être du type attendu par l’objet DbSet et ils sont automatiquement suivis par le contexte de base de données, sauf si vous désactivez le suivi.The returned objects must be of the type expected by the DbSet object, and they're automatically tracked by the database context unless you turn tracking off.

  • Utilisez Database.ExecuteSqlCommand pour les commandes ne se rapportant pas aux requêtes.Use the Database.ExecuteSqlCommand for non-query commands.

Si vous avez besoin d’exécuter une requête qui renvoie des types qui ne sont pas des entités, vous pouvez utiliser ADO.NET avec la connexion de base de données fournie par EF.If you need to run a query that returns types that aren't entities, you can use ADO.NET with the database connection provided by EF. Les données renvoyées ne font pas l’objet d’un suivi par le contexte de base de données, même si vous utilisez cette méthode pour récupérer des types d’entités.The returned data isn't tracked by the database context, even if you use this method to retrieve entity types.

Comme c’est toujours le cas lorsque vous exécutez des commandes SQL dans une application web, vous devez prendre des précautions pour protéger votre site contre des attaques par injection de code SQL.As is always true when you execute SQL commands in a web application, you must take precautions to protect your site against SQL injection attacks. Une manière de procéder consiste à utiliser des requêtes paramétrables pour vous assurer que les chaînes soumises par une page web ne peuvent pas être interprétées comme des commandes SQL.One way to do that is to use parameterized queries to make sure that strings submitted by a web page can't be interpreted as SQL commands. Dans ce didacticiel, vous utiliserez des requêtes paramétrables lors de l’intégration de l’entrée utilisateur dans une requête.In this tutorial you'll use parameterized queries when integrating user input into a query.

Appeler une requête pour retourner des entitésCall a query to return entities

La classe DbSet<TEntity> fournit une méthode que vous pouvez utiliser pour exécuter une requête qui renvoie une entité de type TEntity.The DbSet<TEntity> class provides a method that you can use to execute a query that returns an entity of type TEntity. Pour voir comment cela fonctionne vous allez modifier le code dans la méthode Details du contrôleur Department.To see how this works you'll change the code in the Details method of the Department controller.

Dans DepartmentsController.cs, dans la méthode Details, remplacez le code qui récupère un service par un appel de méthode FromSql, comme indiqué dans le code en surbrillance suivant :In DepartmentsController.cs, in the Details method, replace the code that retrieves a department with a FromSql method call, as shown in the following highlighted code:

public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }

    string query = "SELECT * FROM Department WHERE DepartmentID = {0}";
    var department = await _context.Departments
        .FromSql(query, id)
        .Include(d => d.Administrator)
        .AsNoTracking()
        .FirstOrDefaultAsync();

    if (department == null)
    {
        return NotFound();
    }

    return View(department);
}

Pour vérifier que le nouveau code fonctionne correctement, sélectionnez l’onglet Departments, puis Details pour l’un des services.To verify that the new code works correctly, select the Departments tab and then Details for one of the departments.

Détails du service

Appeler une requête pour retourner d’autres typesCall a query to return other types

Précédemment, vous avez créé une grille de statistiques des étudiants pour la page About, qui montrait le nombre d’étudiants pour chaque date d’inscription.Earlier you created a student statistics grid for the About page that showed the number of students for each enrollment date. Vous avez obtenu les données à partir du jeu d’entités Students (_context.Students) et utilisé LINQ pour projeter les résultats dans une liste d’objets de modèle de vue EnrollmentDateGroup.You got the data from the Students entity set (_context.Students) and used LINQ to project the results into a list of EnrollmentDateGroup view model objects. Supposons que vous voulez écrire le code SQL lui-même plutôt qu’utiliser LINQ.Suppose you want to write the SQL itself rather than using LINQ. Pour ce faire, vous avez besoin d’exécuter une requête SQL qui renvoie autre chose que des objets d’entité.To do that you need to run a SQL query that returns something other than entity objects. Dans EF Core 1.0, une manière de procéder consiste à écrire du code ADO.NET et à obtenir la connexion de base de données à partir d’EF.In EF Core 1.0, one way to do that is write ADO.NET code and get the database connection from EF.

Dans HomeController.cs, remplacez la méthode About par le code suivant :In HomeController.cs, replace the About method with the following code:

public async Task<ActionResult> About()
{
    List<EnrollmentDateGroup> groups = new List<EnrollmentDateGroup>();
    var conn = _context.Database.GetDbConnection();
    try
    {
        await conn.OpenAsync();
        using (var command = conn.CreateCommand())
        {
            string query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount "
                + "FROM Person "
                + "WHERE Discriminator = 'Student' "
                + "GROUP BY EnrollmentDate";
            command.CommandText = query;
            DbDataReader reader = await command.ExecuteReaderAsync();

            if (reader.HasRows)
            {
                while (await reader.ReadAsync())
                {
                    var row = new EnrollmentDateGroup { EnrollmentDate = reader.GetDateTime(0), StudentCount = reader.GetInt32(1) };
                    groups.Add(row);
                }
            }
            reader.Dispose();
        }
    }
    finally
    {
        conn.Close();
    }
    return View(groups);
}

Ajoutez une instruction using :Add a using statement:

using System.Data.Common;

Exécutez l’application et accédez à la page About.Run the app and go to the About page. Elle affiche les mêmes données qu’auparavant.It displays the same data it did before.

Page About

Appeler une requête de mise à jourCall an update query

Supposons que les administrateurs de Contoso University veuillent effectuer des modifications globales dans la base de données, comme par exemple modifier le nombre de crédits pour chaque cours.Suppose Contoso University administrators want to perform global changes in the database, such as changing the number of credits for every course. Si l’université a un grand nombre de cours, il serait inefficace de les récupérer tous sous forme d’entités et de les modifier individuellement.If the university has a large number of courses, it would be inefficient to retrieve them all as entities and change them individually. Dans cette section, vous allez implémenter une page web permettant à l’utilisateur de spécifier un facteur selon lequel il convient de modifier le nombre de crédits pour tous les cours, et vous effectuerez la modification en exécutant une instruction SQL UPDATE.In this section you'll implement a web page that enables the user to specify a factor by which to change the number of credits for all courses, and you'll make the change by executing a SQL UPDATE statement. La page web ressemblera à l’illustration suivante :The web page will look like the following illustration:

Page de mise à jour des crédits de cours

Dans CoursesController.cs, ajoutez les méthodes UpdateCourseCredits pour HttpGet et HttpPost :In CoursesController.cs, add UpdateCourseCredits methods for HttpGet and HttpPost:

public IActionResult UpdateCourseCredits()
{
    return View();
}
[HttpPost]
public async Task<IActionResult> UpdateCourseCredits(int? multiplier)
{
    if (multiplier != null)
    {
        ViewData["RowsAffected"] = 
            await _context.Database.ExecuteSqlCommandAsync(
                "UPDATE Course SET Credits = Credits * {0}",
                parameters: multiplier);
    }
    return View();
}

Lorsque le contrôleur traite une demande HttpGet, rien n’est renvoyé dans ViewData["RowsAffected"] et la vue affiche une zone de texte vide et un bouton d’envoi, comme indiqué dans l’illustration précédente.When the controller processes an HttpGet request, nothing is returned in ViewData["RowsAffected"], and the view displays an empty text box and a submit button, as shown in the preceding illustration.

Lorsque vous cliquez sur le bouton Update, la méthode HttpPost est appelée et le multiplicateur a la valeur entrée dans la zone de texte.When the Update button is clicked, the HttpPost method is called, and multiplier has the value entered in the text box. Le code exécute alors l’instruction SQL qui met à jour les cours et renvoie le nombre de lignes affectées à la vue dans ViewData.The code then executes the SQL that updates courses and returns the number of affected rows to the view in ViewData. Lorsque la vue obtient une valeur RowsAffected, elle affiche le nombre de lignes mis à jour.When the view gets a RowsAffected value, it displays the number of rows updated.

Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Views/Courses, puis cliquez sur Ajouter > Nouvel élément.In Solution Explorer, right-click the Views/Courses folder, and then click Add > New Item.

Dans la boîte de dialogue Ajouter un nouvel élément, cliquez sur ASP.NET Core sous Installé dans le volet gauche, cliquez sur Vue Razor et nommez la nouvelle vue UpdateCourseCredits.cshtml.In the Add New Item dialog, click ASP.NET Core under Installed in the left pane, click Razor View, and name the new view UpdateCourseCredits.cshtml.

Dans Views/Courses/UpdateCourseCredits.cshtml, remplacez le code du modèle par le code suivant :In Views/Courses/UpdateCourseCredits.cshtml, replace the template code with the following code:

@{
    ViewBag.Title = "UpdateCourseCredits";
}

<h2>Update Course Credits</h2>

@if (ViewData["RowsAffected"] == null)
{
    <form asp-action="UpdateCourseCredits">
        <div class="form-actions no-color">
            <p>
                Enter a number to multiply every course's credits by: @Html.TextBox("multiplier")
            </p>
            <p>
                <input type="submit" value="Update" class="btn btn-default" />
            </p>
        </div>
    </form>
}
@if (ViewData["RowsAffected"] != null)
{
    <p>
        Number of rows updated: @ViewData["RowsAffected"]
    </p>
}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Exécutez la méthode UpdateCourseCredits en sélectionnant l’onglet Courses, puis en ajoutant « /UpdateCourseCredits » à la fin de l’URL dans la barre d’adresse du navigateur (par exemple : http://localhost:5813/Courses/UpdateCourseCredits).Run the UpdateCourseCredits method by selecting the Courses tab, then adding "/UpdateCourseCredits" to the end of the URL in the browser's address bar (for example: http://localhost:5813/Courses/UpdateCourseCredits). Entrez un nombre dans la zone de texte :Enter a number in the text box:

Page de mise à jour des crédits de cours

Cliquez sur Mettre à jour.Click Update. Vous voyez le nombre de lignes affectées :You see the number of rows affected:

Page de mise à jour des crédits de cours – lignes affectées

Cliquez sur Revenir à la liste pour afficher la liste des cours avec le nombre révisé de crédits.Click Back to List to see the list of courses with the revised number of credits.

Notez que le code de production garantit que les mises à jour fourniront toujours des données valides.Note that production code would ensure that updates always result in valid data. Le code simplifié indiqué ici peut multiplier le nombre de crédits suffisamment pour générer des nombres supérieurs à 5.The simplified code shown here could multiply the number of credits enough to result in numbers greater than 5. (La propriété Credits a un attribut [Range(0, 5)].) La requête de mise à jour fonctionne, mais des données non valides peuvent provoquer des résultats inattendus dans d’autres parties du système qui supposent que le nombre de crédits est inférieur ou égal à 5.(The Credits property has a [Range(0, 5)] attribute.) The update query would work but the invalid data could cause unexpected results in other parts of the system that assume the number of credits is 5 or less.

Pour plus d’informations sur les requêtes SQL brutes, consultez Requêtes SQL brutes.For more information about raw SQL queries, see Raw SQL Queries.

Examiner les requêtes SQLExamine SQL queries

Il est parfois utile de pouvoir voir les requêtes SQL réelles qui sont envoyées à la base de données.Sometimes it's helpful to be able to see the actual SQL queries that are sent to the database. Les fonctionnalité de journalisation intégrées pour ASP.NET Core sont utilisées automatiquement par EF Core pour écrire des journaux qui contiennent le code SQL pour les requêtes et les mises à jour.Built-in logging functionality for ASP.NET Core is automatically used by EF Core to write logs that contain the SQL for queries and updates. Dans cette section, vous verrez des exemples de journalisation SQL.In this section you'll see some examples of SQL logging.

Ouvrez StudentsController.cs et dans la méthode Details, définissez un point d’arrêt sur l’instruction if (student == null).Open StudentsController.cs and in the Details method set a breakpoint on the if (student == null) statement.

Exécutez l’application en mode débogage et accédez à la page Details d’un étudiant.Run the app in debug mode, and go to the Details page for a student.

Accédez à la fenêtre Output qui indique la sortie de débogage. Vous voyez la requête :Go to the Output window showing debug output, and you see the query:

Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (56ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
SELECT TOP(2) [s].[ID], [s].[Discriminator], [s].[FirstName], [s].[LastName], [s].[EnrollmentDate]
FROM [Person] AS [s]
WHERE ([s].[Discriminator] = N'Student') AND ([s].[ID] = @__id_0)
ORDER BY [s].[ID]
Microsoft.EntityFrameworkCore.Database.Command:Information: Executed DbCommand (122ms) [Parameters=[@__id_0='?'], CommandType='Text', CommandTimeout='30']
SELECT [s.Enrollments].[EnrollmentID], [s.Enrollments].[CourseID], [s.Enrollments].[Grade], [s.Enrollments].[StudentID], [e.Course].[CourseID], [e.Course].[Credits], [e.Course].[DepartmentID], [e.Course].[Title]
FROM [Enrollment] AS [s.Enrollments]
INNER JOIN [Course] AS [e.Course] ON [s.Enrollments].[CourseID] = [e.Course].[CourseID]
INNER JOIN (
    SELECT TOP(1) [s0].[ID]
    FROM [Person] AS [s0]
    WHERE ([s0].[Discriminator] = N'Student') AND ([s0].[ID] = @__id_0)
    ORDER BY [s0].[ID]
) AS [t] ON [s.Enrollments].[StudentID] = [t].[ID]
ORDER BY [t].[ID]

Vous pouvez remarquer ici quelque chose susceptible de vous surprendre : l’instruction SQL sélectionne jusqu’à 2 lignes (TOP(2)) à partir de la table Person.You'll notice something here that might surprise you: the SQL selects up to 2 rows (TOP(2)) from the Person table. La méthode SingleOrDefaultAsync ne se résout pas à 1 ligne sur le serveur.The SingleOrDefaultAsync method doesn't resolve to 1 row on the server. En voici les raisons :Here's why:

  • Si la requête retourne plusieurs lignes, la méthode retourne la valeur Null.If the query would return multiple rows, the method returns null.
  • Pour déterminer si la requête retourne plusieurs lignes, EF doit vérifier s’il retourne au moins 2.To determine whether the query would return multiple rows, EF has to check if it returns at least 2.

Notez que vous n’êtes pas tenu d’utiliser le mode débogage et de vous arrêter à un point d’arrêt pour obtenir la sortie de journalisation dans la fenêtre Output.Note that you don't have to use debug mode and stop at a breakpoint to get logging output in the Output window. C’est simplement un moyen pratique d’arrêter la journalisation au stade où vous voulez examiner la sortie.It's just a convenient way to stop the logging at the point you want to look at the output. Si vous ne le faites pas, la journalisation se poursuit et vous devez revenir en arrière pour rechercher les parties qui vous intéressent.If you don't do that, logging continues and you have to scroll back to find the parts you're interested in.

Créer une couche d’abstractionCreate an abstraction layer

De nombreux développeurs écrivent du code pour implémenter les modèles d’unité de travail et de référentiel comme un wrapper autour du code qui fonctionne avec Entity Framework.Many developers write code to implement the repository and unit of work patterns as a wrapper around code that works with the Entity Framework. Ces modèles sont destinés à créer une couche d’abstraction entre la couche d’accès aux données et la couche de logique métier d’une application.These patterns are intended to create an abstraction layer between the data access layer and the business logic layer of an application. L’implémentation de ces modèles peut favoriser l’isolation de votre application face à des modifications dans le magasin de données et peut faciliter le test unitaire automatisé ou le développement piloté par les tests (TDD).Implementing these patterns can help insulate your application from changes in the data store and can facilitate automated unit testing or test-driven development (TDD). Toutefois, l’écriture de code supplémentaire pour implémenter ces modèles n’est pas toujours le meilleur choix pour les applications qui utilisent EF, et ce pour plusieurs raisons :However, writing additional code to implement these patterns isn't always the best choice for applications that use EF, for several reasons:

  • La classe de contexte EF elle-même isole votre code face au code spécifique de magasin de données.The EF context class itself insulates your code from data-store-specific code.

  • La classe de contexte EF peut agir comme une classe d’unité de travail pour les mises à jour de base de données que vous effectuez à l’aide d’EF.The EF context class can act as a unit-of-work class for database updates that you do using EF.

  • EF inclut des fonctionnalités pour implémenter TDD sans écrire de code de référentiel.EF includes features for implementing TDD without writing repository code.

Pour plus d’informations sur la façon d’implémenter les modèles d’unité de travail et de référentiel, consultez la version Entity Framework 5 de cette série de didacticiels.For information about how to implement the repository and unit of work patterns, see the Entity Framework 5 version of this tutorial series.

Entity Framework Core implémente un fournisseur de base de données en mémoire qui peut être utilisé pour les tests.Entity Framework Core implements an in-memory database provider that can be used for testing. Pour plus d’informations, consultez Tester avec InMemory.For more information, see Test with InMemory.

Détection automatique des modificationsAutomatic change detection

Entity Framework détermine la manière dont une entité a changé (et par conséquent les mises à jour qui doivent être envoyées à la base de données) en comparant les valeurs en cours d’une entité avec les valeurs d’origine.The Entity Framework determines how an entity has changed (and therefore which updates need to be sent to the database) by comparing the current values of an entity with the original values. Les valeurs d’origine sont stockées lorsque l’entité fait l’objet d’une requête ou d’une jointure.The original values are stored when the entity is queried or attached. Certaines des méthodes qui provoquent la détection automatique des modifications sont les suivantes :Some of the methods that cause automatic change detection are the following:

  • DbContext.SaveChangesDbContext.SaveChanges

  • DbContext.EntryDbContext.Entry

  • ChangeTracker.EntriesChangeTracker.Entries

Si vous effectuez le suivi d’un grand nombre d’entités et que vous appelez l’une de ces méthodes de nombreuses fois dans une boucle, vous pouvez obtenir des améliorations significatives des performances en désactivant temporairement la détection automatique des modifications à l’aide de la propriété ChangeTracker.AutoDetectChangesEnabled.If you're tracking a large number of entities and you call one of these methods many times in a loop, you might get significant performance improvements by temporarily turning off automatic change detection using the ChangeTracker.AutoDetectChangesEnabled property. Par exemple :For example:

_context.ChangeTracker.AutoDetectChangesEnabled = false;

Code source et plans de développement EF CoreEF Core source code and development plans

La source d’Entity Framework Core se trouve à l’adresse https://github.com/aspnet/EntityFrameworkCore.The Entity Framework Core source is at https://github.com/aspnet/EntityFrameworkCore. Le dépôt EF Core contient les builds nocturnes, le suivi des problèmes, les spécifications des fonctionnalités, les notes des réunions de conception et la feuille de route de développement futur.The EF Core repository contains nightly builds, issue tracking, feature specs, design meeting notes, and the roadmap for future development. Vous pouvez signaler ou rechercher des bogues, et apporter votre contribution.You can file or find bugs, and contribute.

Bien que le code source soit ouvert, Entity Framework Core est entièrement pris en charge comme produit Microsoft.Although the source code is open, Entity Framework Core is fully supported as a Microsoft product. L’équipe Microsoft Entity Framework garde le contrôle sur le choix des contributions qui sont acceptées et teste toutes les modifications du code pour garantir la qualité de chaque version.The Microsoft Entity Framework team keeps control over which contributions are accepted and tests all code changes to ensure the quality of each release.

Ingénierie à rebours à partir de la base de données existanteReverse engineer from existing database

Pour rétroconcevoir un modèle de données comprenant des classes d’entité issues d’une base de données existante, utilisez la commande scaffold-dbcontext.To reverse engineer a data model including entity classes from an existing database, use the scaffold-dbcontext command. Consultez le didacticiel de prise en main.See the getting-started tutorial.

Utiliser du code dynamique LINQ pour simplifier le codeUse dynamic LINQ to simplify code

Le troisième didacticiel de cette série montre comment écrire du code LINQ en codant en dur les noms des colonnes dans une instruction switch.The third tutorial in this series shows how to write LINQ code by hard-coding column names in a switch statement. Avec deux colonnes sélectionnables, cela fonctionne correctement, mais si vous avez de nombreuses colonnes, le code peut devenir très détaillé.With two columns to choose from, this works fine, but if you have many columns the code could get verbose. Pour résoudre ce problème, vous pouvez utiliser la méthode EF.Property pour spécifier le nom de la propriété sous forme de chaîne.To solve that problem, you can use the EF.Property method to specify the name of the property as a string. Pour tester cette approche, remplacez la méthode Index dans StudentsController par le code suivant.To try out this approach, replace the Index method in the StudentsController with the following code.

 public async Task<IActionResult> Index(
     string sortOrder,
     string currentFilter,
     string searchString,
     int? pageNumber)
 {
     ViewData["CurrentSort"] = sortOrder;
     ViewData["NameSortParm"] = 
         String.IsNullOrEmpty(sortOrder) ? "LastName_desc" : "";
     ViewData["DateSortParm"] = 
         sortOrder == "EnrollmentDate" ? "EnrollmentDate_desc" : "EnrollmentDate";

     if (searchString != null)
     {
         pageNumber = 1;
     }
     else
     {
         searchString = currentFilter;
     }

     ViewData["CurrentFilter"] = searchString;

     var students = from s in _context.Students
                    select s;
     
     if (!String.IsNullOrEmpty(searchString))
     {
         students = students.Where(s => s.LastName.Contains(searchString)
                                || s.FirstMidName.Contains(searchString));
     }

     if (string.IsNullOrEmpty(sortOrder))
     {
         sortOrder = "LastName";
     }

     bool descending = false;
     if (sortOrder.EndsWith("_desc"))
     {
         sortOrder = sortOrder.Substring(0, sortOrder.Length - 5);
         descending = true;
     }

     if (descending)
     {
         students = students.OrderByDescending(e => EF.Property<object>(e, sortOrder));
     }
     else
     {
         students = students.OrderBy(e => EF.Property<object>(e, sortOrder));
     }

     int pageSize = 3;
     return View(await PaginatedList<Student>.CreateAsync(students.AsNoTracking(), 
         pageNumber ?? 1, pageSize));
 }

RemerciementsAcknowledgments

Tom Dykstra et Rick Anderson (twitter @RickAndMSFT) ont rédigé ce didacticiel.Tom Dykstra and Rick Anderson (twitter @RickAndMSFT) wrote this tutorial. Rowan Miller, Diego Vega et d’autres membres de l’équipe Entity Framework ont participé à la revue du code et ont aidé à résoudre les problèmes qui se sont posés lorsque nous avons écrit le code pour ces didacticiels.Rowan Miller, Diego Vega, and other members of the Entity Framework team assisted with code reviews and helped debug issues that arose while we were writing code for the tutorials. John Parente et Paul Goldman ont travaillé sur la mise à jour de ce tutoriel pour ASP.NET Core 2.2.John Parente and Paul Goldman worked on updating the tutorial for ASP.NET Core 2.2.

Résoudre les erreurs courantesTroubleshoot common errors

ContosoUniversity.dll est utilisé par un autre processusContosoUniversity.dll used by another process

Message d’erreur :Error message:

Impossible d’ouvrir ’...bin\Debug\netcoreapp1.0\ContosoUniversity.dll’ en écriture -- ’Le processus ne peut pas accéder au fichier ’...\bin\Debug\netcoreapp1.0\ContosoUniversity.dll’, car il est en cours d’utilisation par un autre processus.Cannot open '...bin\Debug\netcoreapp1.0\ContosoUniversity.dll' for writing -- 'The process cannot access the file '...\bin\Debug\netcoreapp1.0\ContosoUniversity.dll' because it is being used by another process.

Solution :Solution:

Arrêtez le site dans IIS Express.Stop the site in IIS Express. Accédez à la barre d’état système de Windows, recherchez IIS Express, cliquez avec le bouton droit sur son icône, sélectionnez le site Contoso University, puis cliquez sur Arrêter le site.Go to the Windows System Tray, find IIS Express and right-click its icon, select the Contoso University site, and then click Stop Site.

Migration structurée sans code dans les méthodes Up et DownMigration scaffolded with no code in Up and Down methods

Cause possible :Possible cause:

Les commandes CLI d’EF ne ferment et n’enregistrent pas automatiquement des fichiers de code.The EF CLI commands don't automatically close and save code files. Si vous avez des modifications non enregistrées lorsque vous exécutez la commande migrations add, EF ne trouve pas vos modifications.If you have unsaved changes when you run the migrations add command, EF won't find your changes.

Solution :Solution:

Exécutez la commande migrations remove, enregistrez vos modifications de code et réexécutez la commande migrations add.Run the migrations remove command, save your code changes and rerun the migrations add command.

Erreurs lors de l’exécution de la mise à jour de base de donnéesErrors while running database update

Vous pouvez obtenir d’autres erreurs en apportant des modifications au schéma dans une base de données qui comporte déjà des données.It's possible to get other errors when making schema changes in a database that has existing data. Si vous obtenez des erreurs de migration que vous ne pouvez pas résoudre, vous pouvez changer le nom de la base de données dans la chaîne de connexion ou supprimer la base de données.If you get migration errors you can't resolve, you can either change the database name in the connection string or delete the database. Avec une nouvelle base de données, il n’y a pas de données à migrer et la commande de mise à jour de base de données a beaucoup plus de chances de s’exécuter sans erreur.With a new database, there's no data to migrate, and the update-database command is much more likely to complete without errors.

L’approche la plus simple consiste à renommer la base de données en appsettings.json.The simplest approach is to rename the database in appsettings.json. La prochaine fois que vous exécuterez database update, une nouvelle base de données sera créée.The next time you run database update, a new database will be created.

Pour supprimer une base de données dans SSOX, cliquez avec le bouton droit sur la base de données, cliquez sur Supprimer, puis, dans la boîte de dialogue Supprimer la base de données, sélectionnez Fermer les connexions existantes et cliquez sur OK.To delete a database in SSOX, right-click the database, click Delete, and then in the Delete Database dialog box select Close existing connections and click OK.

Pour supprimer une base de données à l’aide de l’interface CLI, exécutez la commande CLI database drop :To delete a database by using the CLI, run the database drop CLI command:

dotnet ef database drop

Erreur lors de la localisation de l’instance SQL ServerError locating SQL Server instance

Message d’erreur :Error Message:

Une erreur liée au réseau ou spécifique à l’instance s’est produite lors de l’établissement d’une connexion à SQL Server.A network-related or instance-specific error occurred while establishing a connection to SQL Server. Le serveur est introuvable ou n’est pas accessible.The server was not found or was not accessible. Vérifiez que le nom de l’instance est correct et que SQL Server est configuré pour autoriser les connexions distantes.Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (fournisseur : Interfaces réseau SQL, erreur : 26 - Erreur lors de la localisation du serveur/de l’instance spécifiés)(provider: SQL Network Interfaces, error: 26 - Error Locating Server/Instance Specified)

Solution :Solution:

Vérifiez la chaîne de connexion.Check the connection string. Si vous avez supprimé manuellement le fichier de base de données, modifiez le nom de la base de données dans la chaîne de construction pour recommencer avec une nouvelle base de données.If you have manually deleted the database file, change the name of the database in the construction string to start over with a new database.

Obtenir le codeGet the code

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

Ressources supplémentairesAdditional resources

Pour plus d’informations sur EF Core, consultez la documentation sur Entity Framework Core.For more information about EF Core, see the Entity Framework Core documentation. Un ouvrage est également disponible : Entity Framework Core in Action.A book is also available: Entity Framework Core in Action.

Pour plus d’informations sur le déploiement d’une application web, consultez Héberger et déployer ASP.NET Core.For information on how to deploy a web app, see Héberger et déployer ASP.NET Core.

Pour plus d’informations sur les autres rubriques associées à ASP.NET Core MVC, par exemple l’authentification et l’autorisation, consultez Présentation d’ASP.NET Core.For information about other topics related to ASP.NET Core MVC, such as authentication and authorization, see Présentation d’ASP.NET Core.

Étapes suivantesNext steps

Dans ce didacticiel, vous avez effectué les actions suivantes :In this tutorial, you:

  • Requêtes SQL brutes exécutéesPerformed raw SQL queries
  • Requête pour retourner des entités appeléeCalled a query to return entities
  • Requête pour retourner d’autres types appeléeCalled a query to return other types
  • Requête de mise à jour appeléeCalled an update query
  • Requêtes SQL examinéesExamined SQL queries
  • Couche d’abstraction crééeCreated an abstraction layer
  • Détection automatique des modifications découverteLearned about Automatic change detection
  • Code source et plans de développement EF Core découvertsLearned about EF Core source code and development plans
  • Utilisation du code dynamique LINQ pour simplifier le code découverteLearned how to use dynamic LINQ to simplify code

Cette étape termine cette série de tutoriels sur l’utilisation d’Entity Framework Core dans une application ASP.NET Core MVC.This completes this series of tutorials on using the Entity Framework Core in an ASP.NET Core MVC application. Cette série a fait appel à une nouvelle base de données ; une alternative consiste à rétroconcevoir un modèle à partir d’une base de données existante.This series worked with a new database; an alternative is to reverse engineer a model from an existing database.