Utilisation des états de l’entité

Cette rubrique explique l’ajout et l’attachement des entités à un contexte et leur traitement par Entity Framework pendant l’opération SaveChanges. Entity Framework s’occupe du suivi de l’état des entités lorsqu’elles sont connectées à un contexte, mais dans des scénarios multiniveau ou de déconnexion, vous pouvez indiquer à EF dans quel état vos entités doivent se trouver. Les techniques présentées dans cette rubrique s’appliquent également aux modèles créés avec Code First et EF Designer.

États de l’entité et SaveChanges

Une entité peut se trouver dans l’un des cinq états définis par l’énumération EntityState. Ces états sont :

  • Ajout : l’entité est suivie par le contexte, mais elle n’existe pas encore dans la base de données
  • Inchangé : l’entité est suivie par le contexte, elle existe dans la base de données et les valeurs de sa propriété n’ont pas changé à partir des valeurs de la base de données
  • Modifié : l’entité est suivie par le contexte, elle existe dans la base de données et certaines (ou toutes les) valeurs de sa propriété ont été modifiées
  • Supprimé : l’entité est suivie par le contexte et existe dans la base de données, mais elle est marquée pour suppression de la base de données au moment du prochain appel à SaveChanges
  • Détaché : L’entité n’est pas suivie par le contexte

SaveChanges effectue différentes opérations pour les entités dans différents états :

  • Les entités inchangées ne sont pas affectées par SaveChanges. Les mises à jour ne sont pas envoyées à la base de données pour les entités dans l’état Inchangé.
  • Les entités ajoutées sont insérées dans la base de données, puis deviennent Inchangées lorsque SaveChanges les retourne.
  • Les entités modifiées sont mises à jour dans la base de données, puis deviennent Inchangées lorsque SaveChanges les retourne.
  • Les entités supprimées sont supprimées de la base de données et détachées du contexte par la suite.

Les exemples suivants montrent comment modifier l’état d’une entité ou d’un graphique d’entité.

Ajout d’une nouvelle entité au contexte

L’ajout d’une nouvelle entité peut se faire en appelant la méthode Ajouter sur DbSet. Cela place l’entité dans l’état Ajouté, ce qui signifie qu’elle va être insérée dans la base de données à chaque appel à SaveChanges. Par exemple :

using (var context = new BloggingContext())
{
    var blog = new Blog { Name = "ADO.NET Blog" };
    context.Blogs.Add(blog);
    context.SaveChanges();
}

Une autre méthode pour ajouter une nouvelle entité au contexte consiste à modifier son état en Ajout. Par exemple :

using (var context = new BloggingContext())
{
    var blog = new Blog { Name = "ADO.NET Blog" };
    context.Entry(blog).State = EntityState.Added;
    context.SaveChanges();
}

Enfin, vous pouvez ajouter une nouvelle entité au contexte en la connectant à une entité déjà suivie. Cela peut se faire en ajoutant la nouvelle entité à la propriété de navigation collection d’une autre entité ou en définissant une propriété de navigation de référence d’une autre entité pour pointer vers la nouvelle entité. Par exemple :

using (var context = new BloggingContext())
{
    // Add a new User by setting a reference from a tracked Blog
    var blog = context.Blogs.Find(1);
    blog.Owner = new User { UserName = "johndoe1987" };

    // Add a new Post by adding to the collection of a tracked Blog
    blog.Posts.Add(new Post { Name = "How to Add Entities" });

    context.SaveChanges();
}

Remarquez que, pour tous ces exemples, si l’entité ajoutée présente des références à d’autres entités qui ne sont pas encore suivies, ces nouvelles entités vont également être ajoutées au contexte et insérées dans la base de données la prochaine au prochain appel à SaveChanges.

Attachement d’une entité existante au contexte

Si vous disposez d’une entité déjà existante dans la base de données, mais sans suivi actuel par le contexte, vous pouvez indiquer au contexte de la suivre à l’aide de la méthode Attacher sur DbSet. L’entité va avoir un état Inchangé dans ce contexte. Par exemple :

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Blogs.Attach(existingBlog);

    // Do some more work...  

    context.SaveChanges();
}

Remarquez qu’aucune modification n’est apportée à la base de données si SaveChanges est appelé sans autre manipulation de l’entité jointe. Cela est dû au fait que l’entité est dans l’état Inchangé.

Une autre méthode pour attacher une entité existante au contexte consiste à modifier son état en Inchangé. Par exemple :

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Entry(existingBlog).State = EntityState.Unchanged;

    // Do some more work...  

    context.SaveChanges();
}

Remarquez que, pour ces deux exemples, si l’entité attachée présente des références à d’autres entités qui ne sont pas encore suivies, ces nouvelles entités vont également être attachées au contexte dans l’état Inchangé.

Attachement d’une entité existante, mais modifiée, au contexte

Si vous disposez d’une entité que vous savez déjà existante dans la base de données, mais possiblement modifiée, vous pouvez indiquer au contexte de l’attacher et définir son état sur Modifié. Par exemple :

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Entry(existingBlog).State = EntityState.Modified;

    // Do some more work...  

    context.SaveChanges();
}

Lorsque vous remplacez l’état par Modifié, toutes les propriétés de l’entité, toutes les propriétés de l’entité sont marquées comme modifiées et toutes les valeurs de la propriété sont envoyées à la base de données au moment de l’appel à SaveChanges.

Remarquez que si l’entité attachée présente des références à d’autres entités qui ne sont pas encore suivies, ces nouvelles entités vont être attachées au contexte dans l’état Inchangé. Elles ne vont pas être automatiquement modifiées. Si vous avez plusieurs entités devant être marquées Modifiées, vous devez individuellement définir leur état.

Modifier l’état d’une entité suivie

Vous pouvez modifier l’état d’une entité déjà suivie en définissant la propriété État sur son entrée. Par exemple :

var existingBlog = new Blog { BlogId = 1, Name = "ADO.NET Blog" };

using (var context = new BloggingContext())
{
    context.Blogs.Attach(existingBlog);
    context.Entry(existingBlog).State = EntityState.Unchanged;

    // Do some more work...  

    context.SaveChanges();
}

Remarquez que l’appel de la méthode Attacher ou Ajouter pour une entité déjà suivie peut également servir à modifier son état. Par exemple, l’appel d’Attach pour une entité actuellement dans l’état Ajouté modifie son état en Inchangé.

Modèle d’insertion ou de mise à jour

Un modèle courant pour certaines applications consiste à Ajouter une entité en tant que nouvelle (entraînant une insertion de la base de données) ou à Attacher une entité comme existante et à la marquer comme modifiée (entraînant une mise à jour de la base de données) en fonction de la valeur de la clé primaire. Par exemple, lors de l’utilisation de clés primaires entières générées par la base de données, une entité avec une clé zéro est habituellement considérée comme nouvelle et celle avec une clé non nulle comme existante. Ce modèle peut être obtenu en définissant l’état d’une entité en fonction d’une vérification de la valeur de la clé primaire. Par exemple :

public void InsertOrUpdate(Blog blog)
{
    using (var context = new BloggingContext())
    {
        context.Entry(blog).State = blog.BlogId == 0 ?
                                   EntityState.Added :
                                   EntityState.Modified;

        context.SaveChanges();
    }
}

Remarquez que lorsque vous modifiez l’état en Modifié, toutes les propriétés de l’entité sont marquées comme modifiées et toutes les valeurs de la propriété sont envoyées à la base de données au moment de l’appel à SaveChanges.