Tutoriel : Implémenter des fonctionnalités CRUD avec Entity Framework dans ASP.NET MVC
Dans le tutoriel précédent, vous avez créé une application MVC qui stocke et affiche des données à l’aide d’Entity Framework (EF) 6 et SQL Server LocalDB. Dans ce tutoriel, vous passez en revue et personnalisez le code de création, de lecture, de mise à jour, de suppression (CRUD) que la structure MVC crée automatiquement pour vous dans les contrôleurs et les vues.
Remarque
Il est courant d’implémenter le modèle de référentiel pour créer une couche d’abstraction entre votre contrôleur et la couche d’accès aux données. Pour simplifier et concentrer ces didacticiels sur l’apprentissage de l’utilisation d’EF 6 lui-même, ils n’utilisent pas de référentiels. Pour plus d’informations sur l’implémentation de référentiels, consultez la ASP.NET Carte de contenu d’accès aux données.
Voici des exemples de pages web que vous créez :
Dans ce tutoriel, vous allez :
- Créer une page Détails
- Mettre à jour la page Create
- Mettre à jour la méthode HttpPost Edit
- Mettre à jour la page Delete
- Fermer les connexions de base de données
- Gérer les transactions
Prérequis
Créer une page Détails
Le code généré automatiquement pour la page Students Index
n’a pas quitté la Enrollments
propriété, car cette propriété contient une collection. Dans la Details
page, vous allez afficher le contenu de la collection dans une table HTML.
Dans Controllers\StudentController.cs, la méthode d’action de la Details
vue utilise la méthode Find pour récupérer une seule Student
entité.
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = db.Students.Find(id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
La valeur de clé est passée à la méthode en tant que id
paramètre et provient des données de routage dans le lien hypertexte Détails de la page Index.
Conseil : Acheminer les données
Les données de routage sont des données que le classeur de modèles trouvé dans un segment d’URL spécifié dans la table de routage. Par exemple, l’itinéraire par défaut spécifie , action
et id
les segments controller
:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Dans l’URL suivante, l’itinéraire par défaut est mappé Instructor
en tant controller
que , Index
comme le action
et 1 comme le id
; il s’agit de valeurs de données de routage.
http://localhost:1230/Instructor/Index/1?courseID=2021
?courseID=2021
est une valeur de chaîne de requête. Le classeur de modèles fonctionne également si vous passez la id
valeur de chaîne de requête :
http://localhost:1230/Instructor/Index?id=1&CourseID=2021
Les URL sont créées par ActionLink
des instructions dans la vue Razor. Dans le code suivant, le id
paramètre correspond à l’itinéraire par défaut. Il est donc id
ajouté aux données de routage.
@Html.ActionLink("Select", "Index", new { id = item.PersonID })
Dans le code suivant, courseID
ne correspond pas à un paramètre dans l’itinéraire par défaut. Il est donc ajouté en tant que chaîne de requête.
@Html.ActionLink("Select", "Index", new { courseID = item.CourseID })
Pour créer la page Détails
Ouvrez Views\Student\Details.cshtml.
Chaque champ s’affiche à l’aide d’un
DisplayFor
assistance, comme illustré dans l’exemple suivant :<dt> @Html.DisplayNameFor(model => model.LastName) </dt> <dd> @Html.DisplayFor(model => model.LastName) </dd>
Après le
EnrollmentDate
champ et juste avant la balise de fermeture</dl>
, ajoutez le code mis en surbrillance pour afficher une liste d’inscriptions, comme illustré dans l’exemple suivant :<dt> @Html.DisplayNameFor(model => model.EnrollmentDate) </dt> <dd> @Html.DisplayFor(model => model.EnrollmentDate) </dd> <dt> @Html.DisplayNameFor(model => model.Enrollments) </dt> <dd> <table class="table"> <tr> <th>Course Title</th> <th>Grade</th> </tr> @foreach (var item in Model.Enrollments) { <tr> <td> @Html.DisplayFor(modelItem => item.Course.Title) </td> <td> @Html.DisplayFor(modelItem => item.Grade) </td> </tr> } </table> </dd> </dl> </div> <p> @Html.ActionLink("Edit", "Edit", new { id = Model.ID }) | @Html.ActionLink("Back to List", "Index") </p>
Si la mise en retrait du code est incorrecte après avoir collé le code, appuyez sur Ctrl+K, Ctrl+D pour la mettre en forme.
Ce code parcourt en boucle les entités dans la propriété de navigation
Enrollments
. Pour chaqueEnrollment
entité de la propriété, elle affiche le titre du cours et la note. Le titre du cours est récupéré à partir de l’entitéCourse
stockée dans laCourse
propriété de navigation de l’entitéEnrollments
. Toutes ces données sont récupérées automatiquement à partir de la base de données quand elles sont nécessaires. En d’autres termes, vous utilisez le chargement différé ici. Vous n’avez pas spécifié de chargement impatient pour laCourses
propriété de navigation, de sorte que les inscriptions n’ont pas été récupérées dans la même requête que celles qui ont obtenu les étudiants. Au lieu de cela, la première fois que vous essayez d’accéder à laEnrollments
propriété de navigation, une nouvelle requête est envoyée à la base de données pour récupérer les données. Vous pouvez en savoir plus sur le chargement différé et le chargement impatient dans le didacticiel Lire les données associées plus loin dans cette série.Ouvrez la page Détails en démarrant le programme (Ctrl+F5), en sélectionnant l’onglet Étudiants, puis en cliquant sur le lien Détails pour Alexander Carson. (Si vous appuyez sur Ctrl+F5 pendant que le fichier Details.cshtml est ouvert, vous obtenez une erreur HTTP 400. Cela est dû au fait que Visual Studio tente d’exécuter la page Détails, mais qu’il n’a pas été atteint à partir d’un lien qui spécifie l’étudiant à afficher. Si cela se produit, supprimez « Student/Details » de l’URL et réessayez, ou fermez le navigateur, cliquez avec le bouton droit sur le projet, puis cliquez sur Afficher>l’affichage dans le navigateur.)
Vous voyez la liste des cours et notes pour l’étudiant sélectionné.
Fermez le navigateur.
Mettre à jour la page Create
Dans Controllers\StudentController.cs, remplacez la HttpPostAttribute
Create
méthode d’action par le code suivant. Ce code ajoute untry-catch
bloc et supprimeID
de l’attribut BindAttribute pour la méthode générée :[HttpPost] [ValidateAntiForgeryToken] public ActionResult Create([Bind(Include = "LastName, FirstMidName, EnrollmentDate")]Student student) { try { if (ModelState.IsValid) { db.Students.Add(student); db.SaveChanges(); return RedirectToAction("Index"); } } catch (DataException /* dex */) { //Log the error (uncomment dex variable name and add a line here to write a log. ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator."); } return View(student); }
Ce code ajoute l’entité
Student
créée par le classeur de modèles MVC ASP.NET auStudents
jeu d’entités, puis enregistre les modifications apportées à la base de données. Le classeur de modèles fait référence à la fonctionnalité MVC ASP.NET qui facilite l’utilisation des données soumises par un formulaire ; un classeur de modèles convertit les valeurs de formulaire publiées en types CLR et les transmet à la méthode d’action dans les paramètres. Dans ce cas, le classeur de modèles instancie uneStudent
entité pour vous à l’aide de valeurs de propriété de laForm
collection.Vous avez supprimé
ID
de l’attribut Bind, carID
est la valeur de clé primaire définie automatiquement par SQL Server lors de l’insertion de la ligne. L’entrée de l’utilisateur ne définit pas laID
valeur.Avertissement de sécurité : l’attribut
ValidateAntiForgeryToken
permet d’empêcher les attaques de falsification de requête intersite. Elle nécessite une instruction correspondanteHtml.AntiForgeryToken()
dans la vue, que vous verrez ultérieurement.L’attribut
Bind
est un moyen de se protéger contre la sur-publication dans les scénarios de création. Par exemple, supposons que l’entitéStudent
inclut uneSecret
propriété que vous ne souhaitez pas définir cette page web.public class Student { public int ID { get; set; } public string LastName { get; set; } public string FirstMidName { get; set; } public DateTime EnrollmentDate { get; set; } public string Secret { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; } }
Même si vous n’avez pas de
Secret
champ sur la page web, un pirate peut utiliser un outil tel que fiddler ou écrire un code JavaScript pour publier uneSecret
valeur de formulaire. Sans l’attribut BindAttribute limitant les champs utilisés par le classeur de modèles lors de la création d’uneStudent
instance, le classeur de modèles récupère cetteSecret
valeur de formulaire et l’utilise pour créer l’instanceStudent
d’entité. Ensuite, la valeur spécifiée par le hacker pour le champ de formulaireSecret
, quelle qu’elle soit, est mise à jour dans la base de données. L’image suivante montre l’outil fiddler qui ajoute leSecret
champ (avec la valeur « OverPost ») aux valeurs de formulaire publiées.La valeur « OverPost » serait correctement ajoutée à la propriété
Secret
de la ligne insérée, même si vous n’aviez jamais prévu que la page web puisse définir cette propriété.Il est préférable d’utiliser le
Include
paramètre avec l’attributBind
pour répertorier explicitement les champs. Il est également possible d’utiliser leExclude
paramètre pour bloquer les champs que vous souhaitez exclure. La raisonInclude
est plus sécurisée : lorsque vous ajoutez une nouvelle propriété à l’entité, le nouveau champ n’est pas automatiquement protégé par uneExclude
liste.Vous pouvez empêcher le surpostage dans les scénarios de modification en lisant d’abord l’entité à partir de la base de données, puis en appelant
TryUpdateModel
, en passant une liste de propriétés autorisées explicite. Il s’agit de la méthode utilisée dans ces didacticiels.Une autre façon d’empêcher le surpostage préféré par de nombreux développeurs consiste à utiliser des modèles d’affichage plutôt que des classes d’entité avec la liaison de modèle. Incluez seulement les propriétés que vous voulez mettre à jour dans le modèle de vue. Une fois le classeur de modèles MVC terminé, copiez les propriétés du modèle d’affichage dans l’instance d’entité, éventuellement à l’aide d’un outil tel que AutoMapper. Utilisez la base de données. Entrée sur l’instance d’entité pour définir son état sur Inchangé, puis définissez Property(« PropertyName »). IsModified à true sur chaque propriété d’entité incluse dans le modèle d’affichage. Cette méthode fonctionne à la fois dans les scénarios de modification et de création.
Autre que l’attribut
Bind
, letry-catch
bloc est la seule modification que vous avez apportée au code généré. Si une exception qui dérive de DataException est interceptée lors de l’enregistrement des modifications, un message d’erreur générique est affiché. Les exceptions DataException sont parfois dues à quelque chose d’externe à l’application et non pas à une erreur de programmation : il est donc conseillé à l’utilisateur de réessayer. Bien que ceci ne soit pas implémenté dans cet exemple, une application destinée à la production doit consigner l’exception. Pour plus d’informations, consultez la section Journal pour obtenir un aperçu de Surveillance et télémétrie (génération d’applications Cloud du monde réel avec Azure).Le code dans Views\Student\Create.cshtml est similaire à ce que vous avez vu dans Details.cshtml, sauf que
EditorFor
lesValidationMessageFor
helpers sont utilisés pour chaque champ au lieu deDisplayFor
. Voici le code correspondant :<div class="form-group"> @Html.LabelFor(model => model.LastName, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.LastName) @Html.ValidationMessageFor(model => model.LastName) </div> </div>
Create.cshtml inclut
@Html.AntiForgeryToken()
également , qui fonctionne avec l’attributValidateAntiForgeryToken
dans le contrôleur pour empêcher les attaques de falsification de requête intersite.Aucune modification n’est requise dans Create.cshtml.
Exécutez la page en démarrant le programme, en sélectionnant l’onglet Étudiants , puis en cliquant sur Créer nouveau.
Entrez des noms et une date non valide, puis cliquez sur Créer pour afficher le message d’erreur.
Il s’agit de la validation côté serveur que vous obtenez par défaut. Dans un didacticiel ultérieur, vous allez découvrir comment ajouter des attributs qui génèrent du code pour la validation côté client. Le code mis en surbrillance suivant montre la vérification de validation du modèle dans la méthode Create .
if (ModelState.IsValid) { db.Students.Add(student); db.SaveChanges(); return RedirectToAction("Index"); }
Changez la date en une valeur valide, puis cliquez sur Create pour voir apparaître le nouvel étudiant dans la page Index.
Fermez le navigateur.
Mettre à jour la méthode HttpPost Edit
Remplacez la méthode d’action HttpPostAttribute
Edit
par le code suivant :[HttpPost, ActionName("Edit")] [ValidateAntiForgeryToken] public ActionResult EditPost(int? id) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } var studentToUpdate = db.Students.Find(id); if (TryUpdateModel(studentToUpdate, "", new string[] { "LastName", "FirstMidName", "EnrollmentDate" })) { try { db.SaveChanges(); return RedirectToAction("Index"); } catch (DataException /* dex */) { //Log the error (uncomment dex variable name and add a line here to write a log. ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator."); } } return View(studentToUpdate); }
Remarque
Dans Controllers\StudentController.cs, la
HttpGet Edit
méthode (celle sans l’attributHttpPost
) utilise laFind
méthode pour récupérer l’entité sélectionnéeStudent
, comme vous l’avez vu dans laDetails
méthode. Vous n’avez pas besoin de modifier cette méthode.Ces modifications implémentent une bonne pratique de sécurité pour empêcher le surpostage, l’échafaudeur a généré un
Bind
attribut et ajouté l’entité créée par le classeur de modèles à l’ensemble d’entités avec un indicateur modifié. Ce code n’est plus recommandé, car l’attributBind
efface toutes les données préexistantes dans les champs non répertoriés dans leInclude
paramètre. À l’avenir, l’échafaudeur du contrôleur MVC sera mis à jour afin qu’il ne génèreBind
pas d’attributs pour les méthodes Edit.Le nouveau code lit l’entité existante et appelle TryUpdateModel pour mettre à jour les champs à partir de l’entrée utilisateur dans les données de formulaire publiées. Le suivi automatique des modifications d’Entity Framework définit l’indicateur EntityState.Modified sur l’entité. Lorsque la méthode SaveChanges est appelée, l’indicateur Modified provoque la création d’instructions SQL par Entity Framework pour mettre à jour la ligne de base de données. Les conflits d’accès concurrentiel sont ignorés et toutes les colonnes de la ligne de base de données sont mises à jour, y compris celles que l’utilisateur n’a pas changé. (Un didacticiel ultérieur montre comment gérer les conflits d’accès concurrentiel et si vous souhaitez uniquement que des champs individuels soient mis à jour dans la base de données, vous pouvez définir l’entité sur EntityState.Unchanged et définissez des champs individuels sur EntityState.Modified.)
Pour empêcher le surpostage, les champs que vous souhaitez mettre à jour par la page Modifier sont répertoriés dans les
TryUpdateModel
paramètres. Actuellement, vous ne protégez aucun champ supplémentaire, mais le fait de répertorier les champs que vous voulez que le classeur de modèles lie garantit que si vous ajoutez ultérieurement des champs au modèle de données, ils seront automatiquement protégés jusqu’à ce que vous les ajoutiez explicitement ici.En raison de ces modifications, la signature de méthode de la méthode HttpPost Edit est la même que la méthode HttpGet edit ; vous avez donc renommé la méthode EditPost.
Conseil
États d’entité et méthodes Attach et SaveChanges
Le contexte de base de données effectue le suivi de la synchronisation ou non des entités en mémoire avec leurs lignes correspondantes dans la base de données, et ces informations déterminent ce qui se passe quand vous appelez la méthode
SaveChanges
. Par exemple, lorsque vous transmettez une nouvelle entité à la méthode Add , l’état de cette entité est définiAdded
sur . Ensuite, lorsque vous appelez la méthode SaveChanges , le contexte de base de données émet une commande SQLINSERT
.Une entité peut être dans l’un des états suivants :
Added
. L’entité n’existe pas encore dans la base de données. LaSaveChanges
méthode doit émettre uneINSERT
instruction.Unchanged
. La méthodeSaveChanges
ne doit rien faire avec cette entité. Quand vous lisez une entité dans la base de données, l’entité a d’abord cet état.Modified
. Tout ou partie des valeurs de propriété de l’entité ont été modifiées. LaSaveChanges
méthode doit émettre uneUPDATE
instruction.Deleted
. L’entité a été marquée pour suppression. LaSaveChanges
méthode doit émettre uneDELETE
instruction.Detached
. L’entité n’est pas suivie par le contexte de base de données.
Dans une application de poste de travail, les changements d’état sont généralement définis automatiquement. Dans un type d’application de bureau, vous lisez une entité et apportez des modifications à certaines de ses valeurs de propriété. Son état passe alors automatiquement à
Modified
. Ensuite, lorsque vous appelezSaveChanges
, Entity Framework génère une instruction SQLUPDATE
qui met à jour uniquement les propriétés réelles que vous avez modifiées.La nature déconnectée des applications web n’autorise pas cette séquence continue. DbContext qui lit une entité est supprimée après le rendu d’une page. Lorsque la
HttpPost
Edit
méthode d’action est appelée, une nouvelle requête est effectuée et vous disposez d’une nouvelle instance de DbContext. Vous devez donc définir manuellement l’étatModified.
de l’entité sur Then lorsque vous appelezSaveChanges
, Entity Framework met à jour toutes les colonnes de la ligne de base de données, car le contexte n’a aucun moyen de savoir quelles propriétés vous avez modifiées.Si vous souhaitez que l’instruction SQL
Update
met à jour uniquement les champs que l’utilisateur a réellement modifiés, vous pouvez enregistrer les valeurs d’origine d’une certaine manière (comme les champs masqués) afin qu’elles soient disponibles lorsque laHttpPost
Edit
méthode est appelée. Vous pouvez ensuite créer uneStudent
entité à l’aide des valeurs d’origine, appeler laAttach
méthode avec cette version d’origine de l’entité, mettre à jour les valeurs de l’entité vers les nouvelles valeurs, puis appelerSaveChanges.
Pour plus d’informations, consultez Les états d’entité et SaveChanges et Les données locales.Le code HTML et Razor dans Views\Student\Edit.cshtml est similaire à ce que vous avez vu dans Create.cshtml et aucune modification n’est requise.
Exécutez la page en démarrant le programme, en sélectionnant l’onglet Étudiants , puis en cliquant sur un lien hypertexte Modifier .
Changez quelques données et cliquez sur Save. Vous voyez les données modifiées dans la page Index.
Fermez le navigateur.
Mettre à jour la page Delete
Dans Controllers\StudentController.cs, le code de modèle de la HttpGetAttribute Delete
méthode utilise la Find
méthode pour récupérer l’entité sélectionnéeStudent
, comme vous l’avez vu dans les méthodes et Edit
les Details
méthodes. Cependant, pour implémenter un message d’erreur personnalisé quand l’appel à SaveChanges
échoue, vous devez ajouter des fonctionnalités à cette méthode et à sa vue correspondante.
Comme vous l’avez vu pour les opérations de mise à jour et de création, les opérations de suppression nécessitent deux méthodes d’action. La méthode appelée en réponse à une requête GET affiche une vue qui permet à l’utilisateur d’approuver ou d’annuler l’opération de suppression. Si l’utilisateur l’approuve, une demande POST est créée. Lorsque cela se produit, la HttpPost
Delete
méthode est appelée, puis cette méthode effectue réellement l’opération de suppression.
Vous allez ajouter un try-catch
bloc à la HttpPostAttribute Delete
méthode pour gérer les erreurs qui peuvent se produire lorsque la base de données est mise à jour. Si une erreur se produit, la HttpPostAttribute Delete
méthode appelle la HttpGetAttribute Delete
méthode, en lui transmettant un paramètre qui indique qu’une erreur s’est produite. La HttpGetAttribute Delete
méthode réaffiche ensuite la page de confirmation avec le message d’erreur, ce qui permet à l’utilisateur d’annuler ou de réessayer.
Remplacez la méthode d’action HttpGetAttribute
Delete
par le code suivant, qui gère le rapport d’erreurs :public ActionResult Delete(int? id, bool? saveChangesError=false) { if (id == null) { return new HttpStatusCodeResult(HttpStatusCode.BadRequest); } if (saveChangesError.GetValueOrDefault()) { ViewBag.ErrorMessage = "Delete failed. Try again, and if the problem persists see your system administrator."; } Student student = db.Students.Find(id); if (student == null) { return HttpNotFound(); } return View(student); }
Ce code accepte un paramètre facultatif qui indique si la méthode a été appelée après un échec d’enregistrement des modifications. Ce paramètre est
false
lorsque laHttpGet
Delete
méthode est appelée sans échec précédent. Lorsqu’elle est appelée par laHttpPost
Delete
méthode en réponse à une erreur de mise à jour de base de données, le paramètre esttrue
et un message d’erreur est transmis à la vue.Remplacez la HttpPostAttribute
Delete
méthode d’action (nomméeDeleteConfirmed
) par le code suivant, qui effectue l’opération de suppression réelle et intercepte les erreurs de mise à jour de base de données.[HttpPost] [ValidateAntiForgeryToken] public ActionResult Delete(int id) { try { Student student = db.Students.Find(id); db.Students.Remove(student); db.SaveChanges(); } catch (DataException/* dex */) { //Log the error (uncomment dex variable name and add a line here to write a log. return RedirectToAction("Delete", new { id = id, saveChangesError = true }); } return RedirectToAction("Index"); }
Ce code récupère l’entité sélectionnée, puis appelle la méthode Remove pour définir l’état
Deleted
de l’entité sur . LorsqueSaveChanges
est appelée, une commande SQLDELETE
est générée. Vous avez également changé le nom de la méthode d’action deDeleteConfirmed
enDelete
. Code généré automatiquement nommé laHttpPost
Delete
méthodeDeleteConfirmed
pour donner à laHttpPost
méthode une signature unique. (Le CLR nécessite des méthodes surchargées pour avoir des paramètres de méthode différents.) Maintenant que les signatures sont uniques, vous pouvez respecter la convention MVC et utiliser le même nom pour les méthodes de suppression etHttpGet
deHttpPost
suppression.Si l’amélioration des performances dans une application à volume élevé est une priorité, vous pouvez éviter une requête SQL inutile pour récupérer la ligne en remplaçant les lignes de code qui appellent le
Find
code etRemove
les méthodes par le code suivant :Student studentToDelete = new Student() { ID = id }; db.Entry(studentToDelete).State = EntityState.Deleted;
Ce code instancie une
Student
entité en utilisant uniquement la valeur de clé primaire, puis définit l’état deDeleted
l’entité sur . C’est tout ce dont a besoin Entity Framework pour pouvoir supprimer l’entité.Comme indiqué, la
HttpGet
Delete
méthode ne supprime pas les données. L’exécution d’une opération de suppression en réponse à une requête GET (ou à ce titre, l’exécution d’une opération de modification, l’opération de création ou toute autre opération qui modifie les données) crée un risque de sécurité.Dans Views\Student\Delete.cshtml, ajoutez un message d’erreur entre le
h2
titre et leh3
titre, comme illustré dans l’exemple suivant :<h2>Delete</h2> <p class="error">@ViewBag.ErrorMessage</p> <h3>Are you sure you want to delete this?</h3>
Exécutez la page en démarrant le programme, en sélectionnant l’onglet Étudiants , puis en cliquant sur un lien hypertexte Supprimer .
Choisissez Supprimer sur la page qui indique Êtes-vous sûr de vouloir le supprimer ?.
La page Index s’affiche sans l’étudiant supprimé. (Vous verrez un exemple de code de gestion des erreurs en action dans le didacticiel d’accès concurrentiel.)
Fermer les connexions de base de données
Pour fermer les connexions de base de données et libérer les ressources qu’ils contiennent dès que possible, supprimez l’instance de contexte lorsque vous l’avez terminé. C’est pourquoi le code généré automatiquement fournit une méthode Dispose à la fin de la StudentController
classe dans StudentController.cs, comme illustré dans l’exemple suivant :
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
La classe de base Controller
implémente déjà l’interface IDisposable
. Ce code ajoute simplement une substitution à la Dispose(bool)
méthode pour supprimer explicitement l’instance de contexte.
Gérer les transactions
Par défaut, Entity Framework implémente implicitement les transactions. Dans les scénarios où vous apportez des modifications à plusieurs lignes ou tables, puis appelez SaveChanges
, Entity Framework garantit automatiquement que toutes vos modifications réussissent ou échouent. Si certaines modifications sont effectuées en premier puis qu’une erreur se produit, ces modifications sont automatiquement annulées. Pour les scénarios où vous avez besoin d’un contrôle supplémentaire( par exemple, si vous souhaitez inclure des opérations effectuées en dehors d’Entity Framework dans une transaction), consultez Utilisation des transactions.
Obtenir le code
Ressources supplémentaires
Vous disposez maintenant d’un ensemble complet de pages qui effectuent des opérations CRUD simples pour Student
les entités. Vous avez utilisé des helpers MVC pour générer des éléments d’interface utilisateur pour les champs de données. Pour plus d’informations sur les helpers MVC, consultez Rendu d’un formulaire à l’aide de l’aide HTML (l’article concerne MVC 3, mais il est toujours pertinent pour MVC 5).
Vous trouverez des liens vers d’autres ressources EF 6 dans ASP.NET Accès aux données - Ressources recommandées.
Étapes suivantes
Dans ce tutoriel, vous allez :
- Page Détails créé
- Mettre à jour la page Create
- Mise à jour de la méthode HttpPost Edit
- Mettre à jour la page Delete
- Connexions de base de données fermées
- Transactions gérées
Passez à l’article suivant pour apprendre à ajouter le tri, le filtrage et la pagination au projet.