Tutoriel : Lire les données associées avec EF dans une application MVC ASP.NET
Dans le tutoriel précédent, vous avez terminé le modèle de données School. Dans ce tutoriel, vous allez lire et afficher les données associées, c’est-à-dire les données que Entity Framework charge dans les propriétés de navigation.
Les illustrations suivantes montrent les pages que vous allez utiliser.
L’exemple d’application web Contoso University montre comment créer ASP.NET applications MVC 5 à l’aide d’Entity Framework 6 Code First et de Visual Studio. Pour obtenir des informations sur la série de didacticiels, consultez le premier didacticiel de la série.
Dans ce tutoriel, vous allez :
- Découvrir comment charger les données associées
- Créer une page Courses
- Créer une page Instructors
Prérequis
Découvrir comment charger les données associées
Il existe plusieurs façons que Entity Framework puisse charger des données associées dans les propriétés de navigation d’une entité :
Chargement différé. Quand l’entité est lue pour la première fois, les données associées ne sont pas récupérées. Toutefois, la première fois que vous essayez d’accéder à une propriété de navigation, les données requises pour cette propriété de navigation sont récupérées automatiquement. Cela entraîne l’envoi de plusieurs requêtes à la base de données : une pour l’entité elle-même et une à chaque fois que les données associées de l’entité doivent être récupérées. La
DbContext
classe active le chargement différé par défaut.Chargement hâtif. Quand l’entité est lue, ses données associées sont également récupérées. Cela génère en général une requête de jointure unique qui récupère toutes les données nécessaires. Vous spécifiez le chargement désireux à l’aide de la
Include
méthode.Chargement explicite. Cela est similaire au chargement différé, sauf que vous récupérez explicitement les données associées dans le code ; cela ne se produit pas automatiquement lorsque vous accédez à une propriété de navigation. Vous chargez manuellement les données associées en obtenant l’entrée du gestionnaire d’état d’objet pour une entité et en appelant la méthode Collection.Load pour les collections ou la méthode Reference.Load pour les propriétés qui contiennent une seule entité. (Dans l’exemple suivant, si vous souhaitez charger la propriété de navigation Administrateur, vous devez remplacer
Collection(x => x.Courses)
parReference(x => x.Administrator)
.) En règle générale, vous n’utilisez le chargement explicite que lorsque vous avez désactivé le chargement différé.
Étant donné qu’ils ne récupèrent pas immédiatement les valeurs de propriété, le chargement différé et le chargement explicite sont également appelés chargement différé.
Considérations relatives aux performances
Si vous savez que vous avez besoin des données associées pour toutes les entités récupérées, le chargement hâtif souvent offre des performances optimales, car une seule requête envoyée à la base de données est généralement plus efficace que les requêtes distinctes pour chaque entité récupérée. Par exemple, dans les exemples ci-dessus, supposons que chaque service a dix cours connexes. L’exemple de chargement désireux entraînerait une seule requête (jointure) et un aller-retour unique vers la base de données. Les exemples de chargement différé et de chargement explicite entraînent à la fois onze requêtes et onze allers-retours vers la base de données. Les allers-retours supplémentaires à la base de données sont particulièrement nuisibles pour les performances lorsque la latence est élevée.
En revanche, dans certains scénarios, le chargement différé est plus efficace. Le chargement désireux peut entraîner la génération d’une jointure très complexe, ce que SQL Server ne peut pas traiter efficacement. Ou si vous avez besoin d’accéder aux propriétés de navigation d’une entité uniquement pour un sous-ensemble d’entités que vous traitez, le chargement différé peut s’avérer plus efficace, car le chargement impatient récupérerait plus de données que nécessaire. Si les performances sont essentielles, il est préférable de tester les performances des deux façons afin d’effectuer le meilleur choix.
Le chargement différé peut masquer le code qui provoque des problèmes de performances. Par exemple, le code qui ne spécifie pas de chargement hâtif ou explicite, mais traite un volume élevé d’entités et utilise plusieurs propriétés de navigation dans chaque itération peut être très inefficace (en raison de nombreux allers-retours vers la base de données). Une application qui effectue un bon développement à l’aide d’un serveur SQL local peut rencontrer des problèmes de performances lors du déplacement vers Azure SQL Database en raison de la latence accrue et du chargement différé. Le profilage des requêtes de base de données avec une charge de test réaliste vous aidera à déterminer si le chargement différé est approprié. Pour plus d’informations, consultez Stratégies Demystifier Entity Framework : chargement de données associées et utilisation d’Entity Framework pour réduire la latence réseau vers SQL Azure.
Désactiver le chargement différé avant la sérialisation
Si vous laissez le chargement différé activé pendant la sérialisation, vous pouvez finir par interroger beaucoup plus de données que prévu. La sérialisation fonctionne généralement en accédant à chaque propriété sur une instance d’un type. L’accès aux propriétés déclenche le chargement différé, et ces entités chargées paresseux sont sérialisées. Le processus de sérialisation accède ensuite à chaque propriété des entités chargées paresseux, ce qui peut entraîner un chargement et une sérialisation encore plus différés. Pour éviter cette réaction de chaîne d’exécution, désactivez le chargement différé avant de sérialiser une entité.
La sérialisation peut également être compliquée par les classes proxy utilisées par Entity Framework, comme expliqué dans le didacticiel Scénarios avancés.
Une façon d’éviter les problèmes de sérialisation consiste à sérialiser des objets de transfert de données (DTO) au lieu d’objets d’entité, comme illustré dans le didacticiel Utilisation de l’API web avec Entity Framework .
Si vous n’utilisez pas DTOs, vous pouvez désactiver le chargement différé et éviter les problèmes de proxy en désactivant la création du proxy.
Voici quelques autres façons de désactiver le chargement différé :
Pour des propriétés de navigation spécifiques, omettez le
virtual
mot clé lorsque vous déclarez la propriété.Pour toutes les propriétés de navigation, définissez
LazyLoadingEnabled
false
sur , placez le code suivant dans le constructeur de votre classe de contexte :this.Configuration.LazyLoadingEnabled = false;
Créer une page Courses
L’entité Course
inclut une propriété de navigation qui contient l’entité Department
du service auquel le cours est affecté. Pour afficher le nom du service affecté dans une liste de cours, vous devez obtenir la Name
propriété à partir de l’entité Department
qui se trouve dans la Course.Department
propriété de navigation.
Créez un contrôleur nommé CourseController
(et non CoursesController) pour le Course
type d’entité, en utilisant les mêmes options pour le contrôleur MVC 5 avec des vues, à l’aide de la structure Entity Framework que vous avez effectuée précédemment pour le Student
contrôleur :
Paramètre | Valeur |
---|---|
Classe Model | Sélectionnez Cours (ContosoUniversity.Models). |
Classe de contexte de données | Sélectionnez SchoolContext (ContosoUniversity.DAL). |
Nom du contrôleur | Entrez CourseController. Là encore, pas CoursesController avec un s. Lorsque vous avez sélectionné Cours (ContosoUniversity.Models), la valeur du nom du contrôleur a été automatiquement remplie. Vous devez modifier la valeur. |
Conservez les autres valeurs par défaut et ajoutez le contrôleur.
Ouvrez Controllers\CourseController.cs et examinez la Index
méthode :
public ActionResult Index()
{
var courses = db.Courses.Include(c => c.Department);
return View(courses.ToList());
}
La génération de modèles automatique a spécifié un chargement hâtif pour la propriété de navigation Department
à l’aide de la méthode Include
.
Ouvrez Views\Course\Index.cshtml et remplacez le code de modèle par le code suivant. Les modifications apparaissent en surbrillance :
@model IEnumerable<ContosoUniversity.Models.Course>
@{
ViewBag.Title = "Courses";
}
<h2>Courses</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.CourseID)
</th>
<th>
@Html.DisplayNameFor(model => model.Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Credits)
</th>
<th>
Department
</th>
<th></th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.CourseID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Title)
</td>
<td>
@Html.DisplayFor(modelItem => item.Credits)
</td>
<td>
@Html.DisplayFor(modelItem => item.Department.Name)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.CourseID }) |
@Html.ActionLink("Details", "Details", new { id=item.CourseID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.CourseID })
</td>
</tr>
}
</table>
Vous avez apporté les modifications suivantes au code généré automatiquement :
- Changement de l’en-tête : Index a été remplacé par Courses.
- Ajout d’une colonne Number qui affiche la valeur de la propriété
CourseID
. Par défaut, les clés primaires ne sont pas générées automatiquement, car normalement elles sont sans signification pour les utilisateurs finaux. Toutefois, dans le cas présent, la clé primaire est significative et vous voulez l’afficher. - Déplace la colonne Department vers le côté droit et modifie son titre. Le générateur de modèles automatique a choisi d’afficher correctement la
Name
propriété à partir de l’entitéDepartment
, mais ici, dans la page Cours, l’en-tête de colonne doit être Department plutôt que Name.
Notez que pour la colonne Department, le code généré automatique affiche la Name
propriété de l’entité Department
chargée dans la Department
propriété de navigation :
<td>
@Html.DisplayFor(modelItem => item.Department.Name)
</td>
Exécutez la page (sélectionnez l’onglet Cours dans la page d’accueil de Contoso University) pour afficher la liste avec des noms de service.
Créer une page Instructors
Dans cette section, vous allez créer un contrôleur et afficher l’entité Instructor
pour afficher la page Instructeurs. Cette page lit et affiche les données associées comme suit :
- La liste des formateurs affiche les données associées de l’entité
OfficeAssignment
. Il existe une relation un-à-zéro-ou-un entre les entitésInstructor
etOfficeAssignment
. Vous allez utiliser un chargement hâtif pour les entitésOfficeAssignment
. Comme expliqué précédemment, le chargement hâtif est généralement plus efficace lorsque vous avez besoin des données associées pour toutes les lignes extraites de la table primaire. Dans ce cas, vous souhaitez afficher les affectations de bureaux pour tous les formateurs affichés. - Quand l’utilisateur sélectionne un formateur, les entités
Course
associées sont affichées. Il existe une relation plusieurs-à-plusieurs entre les entitésInstructor
etCourse
. Vous utilisez le chargement hâtif pour les entitésCourse
et leurs entitésDepartment
associées. Dans ce cas, le chargement différé peut être plus efficace, car vous avez besoin de cours uniquement pour l’instructeur sélectionné. Toutefois, cet exemple montre comment utiliser le chargement hâtif pour des propriétés de navigation dans des entités qui se trouvent elles-mêmes dans des propriétés de navigation. - Quand l’utilisateur sélectionne un cours, les données associées du jeu d’entités
Enrollments
s’affichent. Il existe une relation un-à-plusieurs entre les entitésCourse
etEnrollment
. Vous allez ajouter un chargement explicite pourEnrollment
les entités et leurs entités associéesStudent
. (Le chargement explicite n’est pas nécessaire, car le chargement différé est activé, mais cela montre comment effectuer un chargement explicite.)
Créer un modèle d’affichage pour l’affichage d’index Instructor
La page Instructeurs affiche trois tableaux différents. Par conséquent, vous allez créer un modèle de vue qui comprend trois propriétés, chacune contenant les données d’une des tables.
Dans le dossier ViewModels , créez InstructorIndexData.cs et remplacez le code existant par le code suivant :
using System.Collections.Generic;
using ContosoUniversity.Models;
namespace ContosoUniversity.ViewModels
{
public class InstructorIndexData
{
public IEnumerable<Instructor> Instructors { get; set; }
public IEnumerable<Course> Courses { get; set; }
public IEnumerable<Enrollment> Enrollments { get; set; }
}
}
Créer le contrôleur d’instructeur et les vues
Créez un InstructorController
contrôleur (pas InstructorsController) avec une action de lecture/écriture EF :
Paramètre | Valeur |
---|---|
Classe Model | Sélectionnez Instructeur (ContosoUniversity.Models). |
Classe de contexte de données | Sélectionnez SchoolContext (ContosoUniversity.DAL). |
Nom du contrôleur | Entrez InstructorController. Là encore, pas InstructorsController avec un s. Lorsque vous avez sélectionné Cours (ContosoUniversity.Models), la valeur du nom du contrôleur a été automatiquement remplie. Vous devez modifier la valeur. |
Conservez les autres valeurs par défaut et ajoutez le contrôleur.
Ouvrez Controllers\InstructorController.cs et ajoutez une using
instruction pour l’espace ViewModels
de noms :
using ContosoUniversity.ViewModels;
Le code généré automatiquement dans la Index
méthode spécifie le chargement impatient uniquement pour la propriété de OfficeAssignment
navigation :
public ActionResult Index()
{
var instructors = db.Instructors.Include(i => i.OfficeAssignment);
return View(instructors.ToList());
}
Remplacez la Index
méthode par le code suivant pour charger des données associées supplémentaires et placez-la dans le modèle d’affichage :
public ActionResult Index(int? id, int? courseID)
{
var viewModel = new InstructorIndexData();
viewModel.Instructors = db.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.Courses.Select(c => c.Department))
.OrderBy(i => i.LastName);
if (id != null)
{
ViewBag.InstructorID = id.Value;
viewModel.Courses = viewModel.Instructors.Where(
i => i.ID == id.Value).Single().Courses;
}
if (courseID != null)
{
ViewBag.CourseID = courseID.Value;
viewModel.Enrollments = viewModel.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}
return View(viewModel);
}
La méthode accepte les données de routage facultatives (id
) et un paramètre de chaîne de requête (courseID
) qui fournissent les valeurs d’ID de l’instructeur sélectionné et du cours sélectionné, et transmet toutes les données requises à la vue. Ces paramètres sont fournis par les liens hypertexte Select dans la page.
Le code commence par créer une instance du modèle de vue et la placer dans la liste des formateurs. Le code spécifie le chargement désireux pour la Instructor.OfficeAssignment
propriété de navigation et la propriété de Instructor.Courses
navigation.
var viewModel = new InstructorIndexData();
viewModel.Instructors = db.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.Courses.Select(c => c.Department))
.OrderBy(i => i.LastName);
La deuxième Include
méthode charge Les cours et, pour chaque cours chargé, il effectue un chargement impatient pour la propriété de Course.Department
navigation.
.Include(i => i.Courses.Select(c => c.Department))
Comme mentionné précédemment, le chargement hâtif n’est pas nécessaire, mais il est fait pour améliorer les performances. Étant donné que la vue nécessite toujours l’entité OfficeAssignment
, il est plus efficace de l’extraire dans la même requête. Course
les entités sont requises lorsqu’un instructeur est sélectionné dans la page web, de sorte que le chargement impatient est préférable au chargement différé uniquement si la page est affichée plus souvent avec un cours sélectionné que sans.
Si un ID d’instructeur a été sélectionné, l’instructeur sélectionné est récupéré dans la liste des instructeurs dans le modèle d’affichage. La propriété Courses
du modèle d’affichage est ensuite chargée avec les entités Course
de la propriété de navigation Courses
de ce formateur.
if (id != null)
{
ViewBag.InstructorID = id.Value;
viewModel.Courses = viewModel.Instructors.Where(i => i.ID == id.Value).Single().Courses;
}
La Where
méthode retourne une collection, mais dans ce cas, les critères passés à cette méthode entraînent un seul Instructor
retour d’entité. La méthode Single
convertit la collection en une seule entité Instructor
, ce qui vous permet d’accéder à la propriété Courses
de cette entité.
Vous utilisez la méthode Single sur une collection lorsque vous savez que la collection n’aura qu’un seul élément. La Single
méthode lève une exception si la collection transmise est vide ou s’il y a plusieurs éléments. Une alternative est SingleOrDefault, qui retourne une valeur par défaut (null
dans ce cas) si la collection est vide. Toutefois, dans ce cas, cela entraînerait toujours une exception (d’essayer de trouver une Courses
propriété sur une null
référence) et le message d’exception indiquerait moins clairement la cause du problème. Lorsque vous appelez la Single
méthode, vous pouvez également passer la Where
condition au lieu d’appeler la Where
méthode séparément :
.Single(i => i.ID == id.Value)
À la place de :
.Where(I => i.ID == id.Value).Single()
Ensuite, si un cours a été sélectionné, le cours sélectionné est récupéré à partir de la liste des cours dans le modèle de vue. Ensuite, la propriété du modèle d’affichage Enrollments
est chargée avec les Enrollment
entités de la propriété de navigation de Enrollments
ce cours.
if (courseID != null)
{
ViewBag.CourseID = courseID.Value;
viewModel.Enrollments = viewModel.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}
Modifier l’affichage d’index de l’instructeur
Dans Views\Instructor\Index.cshtml, remplacez le code du modèle par le code suivant. Les modifications apparaissent en surbrillance :
@model ContosoUniversity.ViewModels.InstructorIndexData
@{
ViewBag.Title = "Instructors";
}
<h2>Instructors</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>Last Name</th>
<th>First Name</th>
<th>Hire Date</th>
<th>Office</th>
<th></th>
</tr>
@foreach (var item in Model.Instructors)
{
string selectedRow = "";
if (item.ID == ViewBag.InstructorID)
{
selectedRow = "success";
}
<tr class="@selectedRow">
<td>
@Html.DisplayFor(modelItem => item.LastName)
</td>
<td>
@Html.DisplayFor(modelItem => item.FirstMidName)
</td>
<td>
@Html.DisplayFor(modelItem => item.HireDate)
</td>
<td>
@if (item.OfficeAssignment != null)
{
@item.OfficeAssignment.Location
}
</td>
<td>
@Html.ActionLink("Select", "Index", new { id = item.ID }) |
@Html.ActionLink("Edit", "Edit", new { id = item.ID }) |
@Html.ActionLink("Details", "Details", new { id = item.ID }) |
@Html.ActionLink("Delete", "Delete", new { id = item.ID })
</td>
</tr>
}
</table>
Vous avez apporté les modifications suivantes au code existant :
Vous avez changé la classe de modèle en
InstructorIndexData
.Vous avez changé le titre de la page en remplaçant Index par Instructors.
Ajout d’une colonne Office qui s’affiche
item.OfficeAssignment.Location
uniquement s’ilitem.OfficeAssignment
n’est pas null. (Comme il s’agit d’une relation un-à-zéro-ou-un, il se peut qu’il n’y ait pas d’entité associéeOfficeAssignment
.)<td> @if (item.OfficeAssignment != null) { @item.OfficeAssignment.Location } </td>
Ajout de code qui ajoutera
class="success"
dynamiquement l’élémenttr
de l’instructeur sélectionné. Cela définit une couleur d’arrière-plan pour la ligne sélectionnée à l’aide d’une classe d’amorçage.string selectedRow = ""; if (item.InstructorID == ViewBag.InstructorID) { selectedRow = "success"; } <tr class="@selectedRow" valign="top">
Ajout d’une nouvelle
ActionLink
étiquette Select juste avant les autres liens dans chaque ligne, ce qui entraîne l’envoi de l’ID d’instructeur sélectionné à laIndex
méthode.
Exécutez l’application et sélectionnez l’onglet Instructeurs . La page affiche la Location
propriété des entités associées OfficeAssignment
et une cellule de table vide lorsqu’il n’existe aucune entité associée OfficeAssignment
.
Dans le fichier Views\Instructor\Index.cshtml , après l’élément fermant table
(à la fin du fichier), ajoutez le code suivant. Ce code affiche la liste des cours associés à un formateur quand un formateur est sélectionné.
@if (Model.Courses != null)
{
<h3>Courses Taught by Selected Instructor</h3>
<table class="table">
<tr>
<th></th>
<th>Number</th>
<th>Title</th>
<th>Department</th>
</tr>
@foreach (var item in Model.Courses)
{
string selectedRow = "";
if (item.CourseID == ViewBag.CourseID)
{
selectedRow = "success";
}
<tr class="@selectedRow">
<td>
@Html.ActionLink("Select", "Index", new { courseID = item.CourseID })
</td>
<td>
@item.CourseID
</td>
<td>
@item.Title
</td>
<td>
@item.Department.Name
</td>
</tr>
}
</table>
}
Ce code lit la propriété Courses
du modèle de vue pour afficher la liste des cours. Il fournit également un Select
lien hypertexte qui envoie l’ID du cours sélectionné à la Index
méthode d’action.
Exécutez la page et sélectionnez un instructeur. Vous voyez à présent une grille qui affiche les cours affectés au formateur sélectionné et, pour chaque cours, vous voyez le nom du département affecté.
Après le bloc de code que vous venez d’ajouter, ajoutez le code suivant. Ceci affiche la liste des étudiants qui sont inscrits à un cours quand ce cours est sélectionné.
@if (Model.Enrollments != null)
{
<h3>
Students Enrolled in Selected Course
</h3>
<table class="table">
<tr>
<th>Name</th>
<th>Grade</th>
</tr>
@foreach (var item in Model.Enrollments)
{
<tr>
<td>
@item.Student.FullName
</td>
<td>
@Html.DisplayFor(modelItem => item.Grade)
</td>
</tr>
}
</table>
}
Ce code lit la propriété Enrollments
du modèle de vue pour afficher la liste des étudiants inscrits dans ce cours.
Exécutez la page et sélectionnez un instructeur. Ensuite, sélectionnez un cours pour afficher la liste des étudiants inscrits et leurs notes.
Ajout d’un chargement explicite
Ouvrez InstructorController.cs et examinez comment la Index
méthode obtient la liste des inscriptions pour un cours sélectionné :
if (courseID != null)
{
ViewBag.CourseID = courseID.Value;
viewModel.Enrollments = viewModel.Courses.Where(
x => x.CourseID == courseID).Single().Enrollments;
}
Lorsque vous avez récupéré la liste des instructeurs, vous avez spécifié le chargement désireux pour la Courses
propriété de navigation et pour la Department
propriété de chaque cours. Ensuite, vous placez la Courses
collection dans le modèle d’affichage, et maintenant vous accédez à la Enrollments
propriété de navigation à partir d’une entité de cette collection. Étant donné que vous n’avez pas spécifié de chargement impatient pour la Course.Enrollments
propriété de navigation, les données de cette propriété apparaissent dans la page en raison du chargement différé.
Si vous avez désactivé le chargement différé sans modifier le code d’une autre façon, la Enrollments
propriété serait null, quel que soit le nombre d’inscriptions que le cours avait réellement. Dans ce cas, pour charger la Enrollments
propriété, vous devrez spécifier le chargement désireux ou le chargement explicite. Vous avez déjà vu comment effectuer un chargement impatient. Pour voir un exemple de chargement explicite, remplacez la Index
méthode par le code suivant, qui charge explicitement la Enrollments
propriété. Le code modifié est mis en surbrillance.
public ActionResult Index(int? id, int? courseID)
{
var viewModel = new InstructorIndexData();
viewModel.Instructors = db.Instructors
.Include(i => i.OfficeAssignment)
.Include(i => i.Courses.Select(c => c.Department))
.OrderBy(i => i.LastName);
if (id != null)
{
ViewBag.InstructorID = id.Value;
viewModel.Courses = viewModel.Instructors.Where(
i => i.ID == id.Value).Single().Courses;
}
if (courseID != null)
{
ViewBag.CourseID = courseID.Value;
// Lazy loading
//viewModel.Enrollments = viewModel.Courses.Where(
// x => x.CourseID == courseID).Single().Enrollments;
// Explicit loading
var selectedCourse = viewModel.Courses.Where(x => x.CourseID == courseID).Single();
db.Entry(selectedCourse).Collection(x => x.Enrollments).Load();
foreach (Enrollment enrollment in selectedCourse.Enrollments)
{
db.Entry(enrollment).Reference(x => x.Student).Load();
}
viewModel.Enrollments = selectedCourse.Enrollments;
}
return View(viewModel);
}
Après avoir obtenu l’entité sélectionnée Course
, le nouveau code charge explicitement la propriété de navigation de Enrollments
ce cours :
db.Entry(selectedCourse).Collection(x => x.Enrollments).Load();
Ensuite, il charge explicitement l’entité associée à Student
chaque Enrollment
entité :
db.Entry(enrollment).Reference(x => x.Student).Load();
Notez que vous utilisez la Collection
méthode pour charger une propriété de collection, mais pour une propriété qui contient une seule entité, vous utilisez la Reference
méthode.
Exécutez la page d’index de l’instructeur maintenant et vous ne verrez aucune différence dans ce qui s’affiche sur la page, bien que vous ayez modifié la façon dont les données sont récupérées.
Obtenir le code
Ressources supplémentaires
Vous trouverez des liens vers d’autres ressources Entity Framework dans le ASP.NET Accès aux données - Ressources recommandées.
Étapes suivantes
Dans ce tutoriel, vous allez :
- Chargement des données associées découvert
- Page Courses créée
- Page Instructors créée
Passez à l’article suivant pour découvrir comment mettre à jour les données associées.