Partager via


Scénarios Entity Framework avancés pour une application web MVC (10 sur 10)

par Tom Dykstra

L’exemple d’application web Contoso University montre comment créer ASP.NET applications MVC 4 à l’aide d’Entity Framework 5 Code First et de Visual Studio 2012. Pour obtenir des informations sur la série de didacticiels, consultez le premier didacticiel de la série.

Remarque

Si vous rencontrez un problème, téléchargez le chapitre terminé et essayez de reproduire votre problème. Vous pouvez généralement trouver la solution au problème en comparant votre code au code terminé. Pour certaines erreurs courantes et comment les résoudre, consultez Erreurs et solutions de contournement.

Dans le tutoriel précédent, vous avez implémenté le référentiel et l’unité de travail. Ce tutoriel couvre les rubriques suivantes :

  • Exécution de requêtes SQL brutes.
  • Exécution de requêtes sans suivi.
  • Examen des requêtes envoyées à la base de données.
  • Utilisation de classes proxy.
  • Désactivation de la détection automatique des modifications.
  • Désactivation de la validation lors de l’enregistrement des modifications.
  • Erreurs et contourner les problèmes

Pour la plupart de ces rubriques, vous allez utiliser des pages que vous avez déjà créées. Pour utiliser sql brut pour effectuer des mises à jour en bloc, vous allez créer une page qui met à jour le nombre de crédits de tous les cours de la base de données :

Capture d’écran montrant la page Mettre à jour les crédits de cours initiaux. Le nombre 2 est entré dans le champ de texte.

Pour utiliser une requête sans suivi, vous allez ajouter une nouvelle logique de validation à la page Édition du service :

Capture d’écran montrant la page Modifier du service de l’université Contoso avec un message d’erreur d’administrateur en double.

Exécution de requêtes SQL brutes

L’API Entity Framework Code First inclut des méthodes qui vous permettent de passer des commandes SQL directement à la base de données. Les options suivantes s’offrent à vous :

  • Utilisez la méthode DbSet.SqlQuery pour les requêtes qui renvoient des types d’entités. Les objets retourné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. (Consultez la section suivante sur la AsNoTracking méthode.)
  • Utilisez la Database.SqlQuery méthode pour les requêtes qui retournent des types qui ne sont pas des entités. 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.
  • Utilisez Database.ExecuteSqlCommand pour les commandes non-requête.

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. 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. Toutefois, il existe des scénarios exceptionnels lorsque vous devez exécuter des requêtes SQL spécifiques que vous avez créées manuellement, et ces méthodes vous permettent de gérer ces exceptions.

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. 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. Dans ce didacticiel, vous utiliserez des requêtes paramétrables lors de l’intégration de l’entrée utilisateur dans une requête.

Appel d’une requête qui retourne des entités

Supposons que vous souhaitez que la GenericRepository classe fournisse une flexibilité de filtrage et de tri supplémentaire sans nécessiter de création d’une classe dérivée avec des méthodes supplémentaires. Une façon d’y parvenir consisterait à ajouter une méthode qui accepte une requête SQL. Vous pouvez ensuite spécifier n’importe quel type de filtrage ou de tri souhaité dans le contrôleur, par exemple une Where clause qui dépend d’une jointure ou d’une sous-requête. Dans cette section, vous allez voir comment implémenter une telle méthode.

Créez la GetWithRawSql méthode en ajoutant le code suivant à GenericRepository.cs :

public virtual IEnumerable<TEntity> GetWithRawSql(string query, params object[] parameters)
{
    return dbSet.SqlQuery(query, parameters).ToList();
}

Dans CourseController.cs, appelez la nouvelle méthode à partir de la Details méthode, comme illustré dans l’exemple suivant :

public ActionResult Details(int id)
{
    var query = "SELECT * FROM Course WHERE CourseID = @p0";
    return View(unitOfWork.CourseRepository.GetWithRawSql(query, id).Single());
}

Dans ce cas, vous pourriez avoir utilisé la GetByID méthode, mais vous utilisez la GetWithRawSql méthode pour vérifier que la GetWithRawSQL méthode fonctionne.

Exécutez la page Détails pour vérifier que la requête select fonctionne (sélectionnez l’onglet Cours , puis Détails pour un cours).

Capture d’écran montrant la page Détails de l’université Contoso.

Appel d’une requête qui retourne d’autres types d’objets

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. Le code qui effectue cette opération dans HomeController.cs utilise LINQ :

var data = from student in db.Students
           group student by student.EnrollmentDate into dateGroup
           select new EnrollmentDateGroup()
           {
               EnrollmentDate = dateGroup.Key,
               StudentCount = dateGroup.Count()
           };

Supposons que vous souhaitez écrire le code qui récupère ces données directement dans SQL plutôt que d’utiliser LINQ. Pour ce faire, vous devez exécuter une requête qui retourne quelque chose d’autre que des objets d’entité, ce qui signifie que vous devez utiliser la Database.SqlQuery méthode.

Dans HomeController.cs, remplacez l’instruction LINQ dans la About méthode par le code suivant :

var query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount "
    + "FROM Person "
    + "WHERE EnrollmentDate IS NOT NULL "
    + "GROUP BY EnrollmentDate";
var data = db.Database.SqlQuery<EnrollmentDateGroup>(query);

Exécutez la page About. Elle affiche les mêmes données qu’auparavant.

Capture d’écran montrant la page Contoso University About.

Appel d’une requête de mise à jour

Supposons que les administrateurs de l’Université Contoso souhaitent pouvoir effectuer des modifications en bloc dans la base de données, telles que la modification du nombre de crédits pour chaque cours. 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. Dans cette section, vous allez implémenter une page web qui permet à l’utilisateur de spécifier un facteur par lequel modifier le nombre de crédits pour tous les cours, et vous allez apporter la modification en exécutant une instruction SQL UPDATE . La page web ressemblera à l’illustration suivante :

Capture d’écran montrant la page Initiale Mettre à jour les crédits de cours. Le nombre 2 est entré dans le champ de texte.

Dans le tutoriel précédent, vous avez utilisé le référentiel générique pour lire et mettre à jour Course des entités dans le Course contrôleur. Pour cette opération de mise à jour en bloc, vous devez créer une méthode de dépôt qui n’est pas dans le référentiel générique. Pour ce faire, vous allez créer une classe dédiée CourseRepository qui dérive de la GenericRepository classe.

Dans le dossier DAL , créez CourseRepository.cs et remplacez le code existant par le code suivant :

using System;
using ContosoUniversity.Models;

namespace ContosoUniversity.DAL
{
    public class CourseRepository : GenericRepository<Course>
    {
        public CourseRepository(SchoolContext context)
            : base(context)
        {
        }

        public int UpdateCourseCredits(int multiplier)
        {
            return context.Database.ExecuteSqlCommand("UPDATE Course SET Credits = Credits * {0}", multiplier);
        }

    }
}

Dans UnitOfWork.cs, remplacez le Course type de référentiel par GenericRepository<Course>CourseRepository:

private CourseRepository courseRepository;
public CourseRepository CourseRepository
{
    get
    {

        if (this.courseRepository == null)
        {
            this.courseRepository = new CourseRepository(context);
        }
        return courseRepository;
    }
}

Dans CourseController.cs, ajoutez une UpdateCourseCredits méthode :

public ActionResult UpdateCourseCredits(int? multiplier)
{
    if (multiplier != null)
    {
        ViewBag.RowsAffected = unitOfWork.CourseRepository.UpdateCourseCredits(multiplier.Value);
    }
    return View();
}

Cette méthode sera utilisée pour les deux HttpGet et HttpPost. Lorsque la HttpGet UpdateCourseCredits méthode s’exécute, la multiplier variable est null et la vue affiche une zone de texte vide et un bouton Envoyer, comme illustré dans l’illustration précédente.

Lorsque le bouton Mettre à jour est cliqué et que la HttpPost méthode s’exécute, multiplier la valeur est entrée dans la zone de texte. Le code appelle ensuite la méthode de référentiel UpdateCourseCredits , qui retourne le nombre de lignes affectées et cette valeur est stockée dans l’objet ViewBag . Lorsque l’affichage reçoit le nombre de lignes affectées dans l’objet ViewBag , il affiche ce nombre au lieu de la zone de texte et du bouton Envoyer, comme illustré dans l’illustration suivante :

Capture d’écran montrant les lignes Crédits de cours de mise à jour de l’université Contoso sur la page affectée.

Créez un affichage dans le dossier Views\Course pour la page Mettre à jour les crédits de cours :

Capture d’écran montrant la boîte de dialogue Ajouter un affichage. Mettre à jour les crédits de cours est entré dans le champ texte Afficher le nom.

Dans Views\Course\UpdateCourseCredits.cshtml, remplacez le code de modèle par le code suivant :

@model ContosoUniversity.Models.Course

@{
    ViewBag.Title = "UpdateCourseCredits";
}

<h2>Update Course Credits</h2>

@if (ViewBag.RowsAffected == null)
{
    using (Html.BeginForm())
    {
        <p>
            Enter a number to multiply every course's credits by: @Html.TextBox("multiplier")
        </p>
        <p>
            <input type="submit" value="Update" />
        </p>
    }
}
@if (ViewBag.RowsAffected != null)
{
    <p>
        Number of rows updated: @ViewBag.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:50205/Course/UpdateCourseCredits). Entrez un nombre dans la zone de texte :

Capture d’écran montrant la page initiale Mettre à jour les crédits de cours avec le numéro 2 entré dans le champ de texte.

Cliquez sur Update. Vous voyez le nombre de lignes affectées :

Capture d’écran montrant la page Mettre à jour les crédits de cours avec le nombre de lignes mises à jour.

Cliquez sur Revenir à la liste pour afficher la liste des cours avec le nombre révisé de crédits.

Capture d’écran montrant la page Index des cours. Une liste de cours s’affiche avec le nombre révisé de crédits.

Pour plus d’informations sur les requêtes SQL brutes, consultez le blog des requêtes SQL brutes sur le blog de l’équipe Entity Framework.

Requêtes sans suivi

Lorsqu’un contexte de base de données récupère des lignes de base de données et crée des objets d’entité qui les représentent, par défaut, il suit si les entités en mémoire sont synchronisées avec ce qui se trouve dans la base de données. Les données en mémoire agissent comme un cache et sont utilisées quand vous mettez à jour une entité. Cette mise en cache est souvent inutile dans une application web, car les instances de contexte ont généralement une durée de vie courte (une instance est créée puis supprimée pour chaque requête) et le contexte qui lit une entité est généralement supprimé avant que cette entité soit réutilisée.

Vous pouvez spécifier si le contexte suit les objets d’entité d’une requête à l’aide de la AsNoTracking méthode. Voici des scénarios classiques où vous voulez procéder ainsi :

  • La requête récupère un tel volume de données que la désactivation du suivi peut améliorer sensiblement les performances.
  • Vous souhaitez attacher une entité pour la mettre à jour, mais vous avez précédemment récupéré la même entité à un autre objectif. Comme l’entité est déjà suivie par le contexte de base de données, vous ne pouvez pas attacher l’entité que vous voulez modifier. L’une des façons d’empêcher ce problème est d’utiliser l’option AsNoTracking avec la requête précédente.

Dans cette section, vous allez implémenter la logique métier qui illustre la deuxième de ces scénarios. Plus précisément, vous allez appliquer une règle d’entreprise qui indique qu’un instructeur ne peut pas être l’administrateur de plusieurs services.

Dans DepartmentController.cs, ajoutez une nouvelle méthode que vous pouvez appeler à partir des Edit méthodes et Create pour vous assurer qu’aucun des deux services n’a le même administrateur :

private void ValidateOneAdministratorAssignmentPerInstructor(Department department)
{
    if (department.PersonID != null)
    {
        var duplicateDepartment = db.Departments
            .Include("Administrator")
            .Where(d => d.PersonID == department.PersonID)
            .FirstOrDefault();
        if (duplicateDepartment != null && duplicateDepartment.DepartmentID != department.DepartmentID)
        {
            var errorMessage = String.Format(
                "Instructor {0} {1} is already administrator of the {2} department.",
                duplicateDepartment.Administrator.FirstMidName,
                duplicateDepartment.Administrator.LastName,
                duplicateDepartment.Name);
            ModelState.AddModelError(string.Empty, errorMessage);
        }
    }
}

Ajoutez du code dans le try bloc de la HttpPost Edit méthode pour appeler cette nouvelle méthode s’il n’existe aucune erreur de validation. Le try bloc ressemble maintenant à l’exemple suivant :

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(
   [Bind(Include = "DepartmentID, Name, Budget, StartDate, RowVersion, PersonID")]
    Department department)
{
   try
   {
      if (ModelState.IsValid)
      {
         ValidateOneAdministratorAssignmentPerInstructor(department);
      }

      if (ModelState.IsValid)
      {
         db.Entry(department).State = EntityState.Modified;
         db.SaveChanges();
         return RedirectToAction("Index");
      }
   }
   catch (DbUpdateConcurrencyException ex)
   {
      var entry = ex.Entries.Single();
      var clientValues = (Department)entry.Entity;

Exécutez la page Modification du service et essayez de modifier l’administrateur d’un service en un instructeur qui est déjà l’administrateur d’un autre service. Vous obtenez le message d’erreur attendu :

Capture d’écran montrant la page Department Edit avec un message d’erreur d’administrateur en double.

Exécutez à présent à nouveau la page Modification du service et cette fois changez le montant du budget . Lorsque vous cliquez sur Enregistrer, une page d’erreur s’affiche :

Capture d’écran montrant la page Department Edit avec un message d’erreur du gestionnaire d’état d’objet.

Le message d’erreur d’exception est «An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key. » Cela s’est produit en raison de la séquence d’événements suivante :

  • La Edit méthode appelle la ValidateOneAdministratorAssignmentPerInstructor méthode, qui récupère tous les services qui ont Kim Abercrombie en tant qu’administrateur. Cela entraîne la lecture du département anglais. Étant donné que c’est le service en cours de modification, aucune erreur n’est signalée. En conséquence de cette opération de lecture, toutefois, l’entité de service anglais qui a été lue à partir de la base de données est désormais suivie par le contexte de la base de données.
  • La Edit méthode tente de définir l’indicateur Modified sur l’entité de service anglais créée par le classeur de modèles MVC, mais cela échoue, car le contexte suit déjà une entité pour le service anglais.

Une solution à ce problème consiste à empêcher le contexte de suivre les entités de service en mémoire récupérées par la requête de validation. Cela n’entraîne aucun inconvénient, car vous n’allez pas mettre à jour cette entité ou la lire de nouveau d’une manière qui tirerait parti de sa mise en cache en mémoire.

Dans DepartmentController.cs, dans la ValidateOneAdministratorAssignmentPerInstructor méthode, spécifiez aucun suivi, comme indiqué dans les éléments suivants :

var duplicateDepartment = db.Departments
   .Include("Administrator")
   .Where(d => d.PersonID == department.PersonID)
   .AsNoTracking()
   .FirstOrDefault();

Répétez votre tentative de modification du montant budgétaire d’un service. Cette fois que l’opération réussit et que le site est retourné comme prévu dans la page Index des services, affichant la valeur budgétaire révisée.

Examen des requêtes envoyées à la base de données

Il est parfois utile de pouvoir voir les requêtes SQL réelles qui sont envoyées à la base de données. Pour ce faire, vous pouvez examiner une variable de requête dans le débogueur ou appeler la méthode de ToString la requête. Pour essayer cette opération, vous allez examiner une requête simple, puis examiner ce qui se passe quand vous ajoutez des options telles que le chargement, le filtrage et le tri désireux.

Dans Controllers/CourseController, remplacez la Index méthode par le code suivant :

public ViewResult Index()
{
    var courses = unitOfWork.CourseRepository.Get();
    return View(courses.ToList());
}

Définissez maintenant un point d’arrêt dans GenericRepository.cs sur les return query.ToList(); instructions et les return orderBy(query).ToList(); instructions de la Get méthode. Exécutez le projet en mode débogage et sélectionnez la page Index du cours. Lorsque le code atteint le point d’arrêt, examinez la query variable. Vous voyez la requête envoyée à SQL Server. Il s’agit d’une instruction simple Select :

{SELECT 
[Extent1].[CourseID] AS [CourseID], 
[Extent1].[Title] AS [Title], 
[Extent1].[Credits] AS [Credits], 
[Extent1].[DepartmentID] AS [DepartmentID]
FROM [Course] AS [Extent1]}

Capture d’écran montrant l’exemple d’onglet Référentiel générique d’application web. La variable de requête est sélectionnée.

Les requêtes peuvent être trop longues pour s’afficher dans les fenêtres de débogage dans Visual Studio. Pour afficher l’intégralité de la requête, vous pouvez copier la valeur de la variable et la coller dans un éditeur de texte :

Capture d’écran montrant la valeur de la variable avec un menu déroulant affiché lorsqu’elle est sélectionnée. L’option Copier la valeur est mise en surbrillance.

Vous allez maintenant ajouter une liste déroulante à la page Index de cours afin que les utilisateurs puissent filtrer pour un service particulier. Vous allez trier les cours par titre, et vous spécifiez le chargement désireux pour la propriété de Department navigation. Dans CourseController.cs, remplacez la Index méthode par le code suivant :

public ActionResult Index(int? SelectedDepartment)
{
    var departments = unitOfWork.DepartmentRepository.Get(
        orderBy: q => q.OrderBy(d => d.Name));
    ViewBag.SelectedDepartment = new SelectList(departments, "DepartmentID", "Name", SelectedDepartment);

    int departmentID = SelectedDepartment.GetValueOrDefault(); 
    return View(unitOfWork.CourseRepository.Get(
        filter: d => !SelectedDepartment.HasValue || d.DepartmentID == departmentID,
        orderBy: q => q.OrderBy(d => d.CourseID),
        includeProperties: "Department"));
}

La méthode reçoit la valeur sélectionnée de la liste déroulante dans le SelectedDepartment paramètre. Si rien n’est sélectionné, ce paramètre est null.

Une SelectList collection contenant tous les services est transmise à l’affichage de la liste déroulante. Les paramètres transmis au constructeur spécifient le nom du SelectList champ valeur, le nom du champ de texte et l’élément sélectionné.

Pour la Get méthode du Course référentiel, le code spécifie une expression de filtre, un ordre de tri et un chargement impatient pour la Department propriété de navigation. L’expression de filtre retourne true toujours si rien n’est sélectionné dans la liste déroulante (autrement dit, SelectedDepartment est null).

Dans Views\Course\Index.cshtml, juste avant la balise d’ouverture table , ajoutez le code suivant pour créer la liste déroulante et un bouton Envoyer :

@using (Html.BeginForm())
{
    <p>Select Department: @Html.DropDownList("SelectedDepartment","All")   
    <input type="submit" value="Filter" /></p>
}

Avec les points d’arrêt toujours définis dans la GenericRepository classe, exécutez la page Index de cours. Passez par les deux premières fois que le code atteint un point d’arrêt, afin que la page s’affiche dans le navigateur. Sélectionnez un service dans la liste déroulante, puis cliquez sur Filtrer :

Capture d’écran montrant la page Index de cours avec le Département économique sélectionné.

Cette fois, le premier point d’arrêt concerne la requête des services pour la liste déroulante. Ignorez cette variable et affichez la query variable la prochaine fois que le code atteint le point d’arrêt pour voir à quoi ressemble maintenant la Course requête. Vous verrez quelque chose comme suit :

{SELECT 
[Extent1].[CourseID] AS [CourseID], 
[Extent1].[Title] AS [Title], 
[Extent1].[Credits] AS [Credits], 
[Extent1].[DepartmentID] AS [DepartmentID], 
[Extent2].[DepartmentID] AS [DepartmentID1], 
[Extent2].[Name] AS [Name], 
[Extent2].[Budget] AS [Budget], 
[Extent2].[StartDate] AS [StartDate], 
[Extent2].[PersonID] AS [PersonID], 
[Extent2].[Timestamp] AS [Timestamp]
FROM  [Course] AS [Extent1]
INNER JOIN [Department] AS [Extent2] ON [Extent1].[DepartmentID] = [Extent2].[DepartmentID]
WHERE (@p__linq__0 IS NULL) OR ([Extent1].[DepartmentID] = @p__linq__1)}

Vous pouvez voir que la requête est désormais une JOIN requête qui charge des Department données avec les Course données, et qu’elle inclut une WHERE clause.

Utilisation de classes proxy

Lorsque Entity Framework crée des instances d’entité (par exemple, lorsque vous exécutez une requête), elle les crée souvent en tant qu’instances d’un type dérivé généré dynamiquement qui agit en tant que proxy pour l’entité. Ce proxy remplace certaines propriétés virtuelles de l’entité pour insérer des hooks pour effectuer des actions automatiquement lorsque la propriété est accessible. Par exemple, ce mécanisme est utilisé pour prendre en charge le chargement différé de relations.

La plupart du temps, vous n’avez pas besoin de connaître cette utilisation de proxys, mais il existe des exceptions :

  • Dans certains scénarios, vous pouvez empêcher Entity Framework de créer des instances proxy. Par exemple, la sérialisation d’instances non proxy peut être plus efficace que la sérialisation des instances proxy.
  • Lorsque vous instanciez une classe d’entité à l’aide de l’opérateur new , vous n’obtenez pas d’instance proxy. Cela signifie que vous n’obtenez pas de fonctionnalités telles que le chargement différé et le suivi automatique des modifications. C’est généralement correct ; vous n’avez généralement pas besoin de chargement différé, car vous créez une entité qui n’est pas dans la base de données, et vous n’avez généralement pas besoin de suivi des modifications si vous marquez explicitement l’entité comme Added. Toutefois, si vous avez besoin d’un chargement différé et que vous avez besoin d’un suivi des modifications, vous pouvez créer de nouvelles instances d’entité avec des proxys à l’aide de la Create méthode de la DbSet classe.
  • Vous souhaiterez peut-être obtenir un type d’entité réel à partir d’un type proxy. Vous pouvez utiliser la GetObjectType méthode de la ObjectContext classe pour obtenir le type d’entité réel d’une instance de type proxy.

Pour plus d’informations, consultez Utilisation de proxys sur le blog de l’équipe Entity Framework.

Désactivation de la détection automatique des modifications

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. Les valeurs d’origine sont stockées lorsque l’entité a été interrogée ou jointe. Certaines des méthodes qui provoquent la détection automatique des modifications sont les suivantes :

  • DbSet.Find
  • DbSet.Local
  • DbSet.Remove
  • DbSet.Add
  • DbSet.Attach
  • DbContext.SaveChanges
  • DbContext.GetValidationErrors
  • DbContext.Entry
  • DbChangeTracker.Entries

Si vous effectuez le suivi d’un grand nombre d’entités et que vous appelez l’une de ces méthodes plusieurs 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é AutoDetectChangesEnabled . Pour plus d’informations, consultez Détection automatique des modifications.

Désactivation de la validation lors de l’enregistrement des modifications

Lorsque vous appelez la SaveChanges méthode, par défaut, Entity Framework valide les données dans toutes les propriétés de toutes les entités modifiées avant de mettre à jour la base de données. Si vous avez mis à jour un grand nombre d’entités et que vous avez déjà validé les données, ce travail n’est pas nécessaire et vous pouvez faire en sorte que le processus d’enregistrement des modifications prenne moins de temps en désactivant temporairement la validation. Pour ce faire, utilisez la propriété ValidateOnSaveEnabled . Pour plus d’informations, consultez Validation.

Résumé

Cette série de didacticiels est terminée sur l’utilisation d’Entity Framework dans une application MVC ASP.NET. Vous trouverez des liens vers d’autres ressources Entity Framework dans la carte de contenu d’accès aux données ASP.NET.

Pour plus d’informations sur le déploiement de votre application web une fois que vous l’avez créée, consultez ASP.NET Mappage de contenu de déploiement dans MSDN Library.

Pour plus d’informations sur d’autres rubriques relatives à MVC, telles que l’authentification et l’autorisation, consultez les ressources recommandées MVC.

Remerciements

  • Tom Dykstra a écrit la version d’origine de ce tutoriel et est un rédacteur de programmation senior sur l’équipe de contenu microsoft Web Platform and Tools.
  • Rick Anderson (twitter @RickAndMSFT) a co-créé ce tutoriel et a effectué la plupart du travail de mise à jour pour EF 5 et MVC 4. Rick est un rédacteur en programmation senior pour Microsoft qui se concentre sur Azure et MVC.
  • Rowan Miller et d’autres membres de l’équipe Entity Framework ont assisté à des révisions de code et ont aidé à déboguer de nombreux problèmes liés aux migrations qui se sont produites lors de la mise à jour du didacticiel pour EF 5.

VB

Lorsque le didacticiel a été produit à l’origine, nous avons fourni les versions C# et VB du projet de téléchargement terminé. Avec cette mise à jour, nous proposons un projet téléchargeable C# pour chaque chapitre afin de faciliter la prise en main n’importe où dans la série, mais en raison de limitations temporelles et d’autres priorités, nous n’avons pas fait cela pour VB. Si vous créez un projet VB à l’aide de ces didacticiels et souhaitez le partager avec d’autres personnes, veuillez nous le faire savoir.

Erreurs et solutions alternatives

Impossible de créer/de cliché instantané

Message d’erreur :

Impossible de créer/de cliché instantané « DotNetOpenAuth.OpenId » quand ce fichier existe déjà.

Solution :

Patientez quelques secondes et actualisez la page.

Update-Database non reconnu

Message d’erreur :

Le terme « Update-Database » n’est pas reconnu comme nom d’une applet de commande, d’une fonction, d’un fichier de script ou d’un programme opérable. Vérifiez l’orthographe du nom ou, si un chemin d’accès a été inclus, vérifiez que le chemin d’accès est correct et réessayez.(À partir de la Update-Database commande dans pmc.)

Solution :

Quittez Visual Studio. Rouvrez le projet et réessayez.

Échec de la validation

Message d’erreur :

La validation a échoué pour une ou plusieurs entités. Pour plus d’informations, consultez la propriété « EntityValidationErrors ». (À partir de la Update-Database commande dans pmc.)

Solution :

L’une des causes de ce problème est les erreurs de validation lors de l’exécution de la Seed méthode. Pour obtenir des conseils sur le débogage de la Seed méthode, consultez amorçage et débogage des bases de données Entity Framework (EF).

Erreur HTTP 500.19

Message d’erreur :

Erreur HTTP 500.19 - Erreur du serveur interne
Impossible d’accéder à la page demandée, car les données de configuration associées pour la page ne sont pas valides.

Solution :

Une façon d’obtenir cette erreur consiste à avoir plusieurs copies de la solution, chacune d’entre elles utilisant le même numéro de port. Vous pouvez généralement résoudre ce problème en quittant toutes les instances de Visual Studio, puis en redémarrant le projet sur lequel vous travaillez. Si cela ne fonctionne pas, essayez de modifier le numéro de port. Cliquez avec le bouton droit sur le fichier projet, puis cliquez sur Propriétés. Sélectionnez l’onglet Web, puis modifiez le numéro de port dans la zone de texte URL du projet.

Erreur lors de la localisation de l’instance SQL Server

Message d’erreur :

Une erreur liée au réseau ou propre à une instance s’est produite lors de l’établissement d’une connexion à SQL Server. Le serveur est introuvable ou inaccessible. Vérifiez que le nom de l’instance est correct et que SQL Server est configuré pour autoriser les connexions à distance. (fournisseur : interfaces réseau SQL, erreur : 26 - Erreur lors de la localisation du serveur/de l’instance spécifiés)

Solution :

Vérifiez chaîne de connexion. Si vous avez supprimé manuellement la base de données, modifiez le nom de la base de données dans la chaîne de construction.