web-dev-qa-db-fra.com

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 il en existe 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 mettre le cache dans un projet ASP.NET, par exemple). Cependant, comme je ne peux pas détacher une entité, lorsque j'essaie de joindre une entité qui était associée à un contexte précédent, j'obtiens l'exception "Un objet entité ne peut pas être référencé par plusieurs instances de IEntityChangeTracker".

Quels sont les conseils ici? Suis-je en train de manquer quelque chose?

62
Brian Sullivan

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

((IObjectContextAdapter)context).ObjectContext

afin d'accéder à ObjectContext.

85
Joakim

DbContext utilise un ObjectContext en interne et l'équipe EF le rend disponible en tant que propriété protected au cas où vous auriez besoin de passer à l'API de niveau inférieur et que cela ressemble à ce qui est le cas ici, vous pouvez donc utiliser ou exposer les fonctionnalités requises à partir d'un DbContext dérivé:

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

Ensuite, vous pouvez appeler cette méthode depuis votre contrôleur pour détacher une entité.

Alternativement, vous pouvez le changer pour avoir même une API plus riche:

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

Voici à quoi ressemble DbContext à partir des métadonnées:

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

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

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 "Détacher est une technologie trop avancée et doit être masquée". À mon humble avis, l'homme qui a inventé cela devrait être abattu - car si vous ajoutez une nouvelle entité, il est autrement difficile de la supprimer sans valider les modifications de db (vous pouvez manipuler avec DbEntityEntry mais c'est une autre histoire).

Modifier 4 ans plus tard:

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

16
Jan 'splite' K.

J'étends généralement la classe de base (hérite de DbContext) avec la propriété:

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

plus tard, vous pouvez utiliser cette propriété pour une variété de choses utiles ... comme Détacher :)

7
Stefan Michev