62 votes

Entity Framework Code First - Pas de méthode Detach() sur DbContext

Je me demande pourquoi il n'y a pas de méthode Detach sur l'objet DbContext comme c'est le cas pour ObjectContext. Je ne peux que supposer que cette omission était intentionnelle, mais j'ai du mal à comprendre pourquoi. J'ai besoin de pouvoir détacher et rattacher des entités (pour les mettre dans le cache d'un projet ASP.NET, par exemple). Cependant, comme je ne peux pas détacher une entité, lorsque j'essaie d'attacher une entité qui était associée à un contexte précédent, j'obtiens l'exception "An entity object cannot be referenced by multiple instances of IEntityChangeTracker" (Un objet entité ne peut pas être référencé par plusieurs instances de IEntityChangeTracker).

Quelle est l'orientation à suivre ? Ai-je raté quelque chose ?

85voto

Joakim Points 1772

Pour les personnes qui tomberaient sur cette question, à partir de la CTP5, vous devez maintenant écrire

((IObjectContextAdapter)context).ObjectContext

pour accéder à ObjectContext.

37voto

Morteza Manavi Points 20486

DbContext utilise un ObjectContext en interne et l'équipe EF le met à disposition en tant que fichier protégé juste au cas où vous auriez besoin de descendre au niveau inférieur de l'API, ce qui semble être le cas ici, afin que vous puissiez utiliser ou exposer la fonctionnalité requise à partir d'un DbContext dérivé :

public class YourContext : DbContext 
{
    public void Detach(object entity) 
    {
        ObjectContext.Detach(entity);            
    }
}

Vous pouvez ensuite appeler cette méthode à partir de votre contrôleur pour détacher une entité.

Vous pouvez également le modifier pour avoir une API plus riche :

public class YourContext : DbContext
{
    public void ChangeObjectState(object entity, EntityState entityState)
    {
        ObjectContext.ObjectStateManager.ChangeObjectState(entity, entityState);
    }
}

Voici à quoi ressemble DbContext d'après les métadonnées :

public class DbContext : IDisposable 
{      
    protected System.Data.Objects.ObjectContext ObjectContext { get; }
    ...
}

16voto

splite Points 321

EF:CF 4.1 RC1 y EF:CF 4.1 RTW ont le même adaptateur IObjectContextAdapter explicitement implémenté :

public static class DbContextExtensions
{
    public static void Detach(this System.Data.Entity.DbContext context, object entity)
    {
         ((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.Detach(entity);
    }
}

Microsoft a décidé que "Detach est une technologie trop avancée et doit être cachée". En effet, si vous ajoutez une nouvelle entité, il est difficile de la supprimer sans modifier la base de données (vous pouvez manipuler DbEntityEntry, mais c'est une autre histoire).

Editer 4 ans plus tard :

Avec EF6 (j'ai en quelque sorte omis EF5 :) ) vous n'avez pas besoin de detach() plus, parce que la suppression d'une entrée fraîchement ajoutée ne génère pas de delete from [table] where [Id] = 0 comme dans EF4 - vous pouvez simplement appeler mySet.Remove(myFreshlyCreatedAndAddedEntity) et tout ira bien.

7voto

Stefan Michev Points 131

J'ai l'habitude d'étendre la classe de base (qui hérite du DbContext) avec la propriété :

public class MyDbContext : DbContext
{
    public ObjectContext ThisObjectContext
    {
        get
        {
            return ((IObjectContextAdapter)this).ObjectContext;
        }
    }
}

plus tard, vous pourrez utiliser cette propriété pour toute une série de choses utiles ... comme Detach :)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X