2010-11-12 3 views
62

Je me demande pourquoi il n'y a pas de méthode Detach sur l'objet DbContext comme pour ObjectContext. Je ne peux que supposer que cette omission était intentionnelle, mais j'ai du mal à comprendre pourquoi. Je dois pouvoir détacher et réattacher des entités (pour mettre le cache dans un projet ASP.NET, par exemple). Cependant, étant donné que je ne peux pas détacher une entité, lorsque j'essaie de joindre une entité associée à un contexte précédent, l'exception "Un objet d'entité ne peut pas être référencé par plusieurs instances d'IEntityChangeTracker".Entity Framework Code Première - Aucune méthode Detach() sur DbContext

Quel est le guide ici? Est-ce que je manque quelque chose?

+0

Quelqu'un at-il quoi que ce soit à dire sur: "Quelle est la direction ici? Suis-je manquer quelque chose?" Personnellement, je ne suis intéressé que par l'utilisation de Detach lors de la recherche d'une solution pour lire une entité à partir du contexte, juste avant de sauvegarder l'instance provenant de l'interface utilisateur. Cela me donne "Un objet avec la même clé existe déjà dans ObjectStateManager.ObjectStateManager ne peut pas suivre plusieurs objets avec la même clé. " –

Répondre

85

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

((IObjectContextAdapter)context).ObjectContext 

afin d'obtenir ObjectContext.

+1

+1 besoin de référencer System.Data.Entity – Pandincus

+0

+1 Nettoyer, élégant, un liner Je l'aime aussi Je voulais aussi jeter que l'interface se trouve ici spécifiquement: System.Data.Entity.Infrastructure.IObjectContextAdapter et oui comme Pandincus a souligné vous devez également faire référence à System.Data.Entity – dyslexicanaboko

38

DbContext utilise un ObjectContext interne et l'équipe EF en font disponible en protégé propriété juste au cas où vous avez besoin de descendre à l'API de niveau inférieur et des sons comme celui-ci est le cas ici, de sorte que vous pouvez utiliser ou exposer la fonctionnalité requise d'un dérivé DbContext:

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

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

Vous pouvez changer d'avoir même une API plus riche:

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

Voici comment DbContext ressemble de métadonnées:

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

@Stacker ce n'est pas la réponse car elle nécessite le cast décrit dans la réponse sélectionnée ci-dessus, ie' DbContext' implémente 'IObjectContextAdapter' en lui donnant la propriété' ObjectContext' qui est Combiner les 2 réponses donne la réponse @ splite ci-dessous – eudaimos

+1

ChangeObjectState est assez paresseux, son utilisation "algorithme linéaire avec moulage" qui est ... Sorte de ... Vous savez ... Reeeeally bad –

15

EF: CF 4.1 RC1 et EF: CF 4.1 RTW ont la même IObjectContextAdapter explicitement mis en œuvre:

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

Edit 4 ans plus tard:

Avec EF6 (i en quelque sorte sautées EF5 :)) vous ne avez pas besoin detach() plus, becouse enlever l'entrée fraîchement ajouté ne génère pas delete from [table] where [Id] = 0 comme dans EF4 - vous pouvez simplement appeler mySet.Remove(myFreshlyCreatedAndAddedEntity) et Tout va bien se passer.

+0

shot? Qui a besoin de cette fonctionnalité de toute façon?: P – quetzalcoatl

+1

@quetzalcoatl: 'var context = ...; var poco = nouveau Poco(); context.Add (poco); context.Remove (poco); '<--- jette une exception parce que vous devez le DÉTACHER, pas enlever - hey, détacher est caché ... –

+1

(5 min pour edit allé, sry :)) À ce moment j'étais tellement fâché ... Lorsque vous faites une application Windows, vous devez avoir un moyen de "annuler la création de nouvelles entrées, probablement incomplètes, mais garder le contexte" ... Nous nous débarrassons de tout EF btw, et écrire notre propre ORM: Il est aucun moyen d'utiliser le chargement paresseux (j'ai tas de factures et je ne peux pas charger chaque InvoiceItem en single "où InvoiceId dans (xxyy)" query - Include ne fonctionne pas comme prévu), plus grands dépôts sont sooooo paresseux (linéaire (!!!) recherche, avant chaque exécution, wtf ...), créer des proxies pour 100 + types de poco prennent trop de temps et ainsi de suite ... –

6

Je s'étendre généralement la classe de base (hérite de la 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 la variété de choses utiles ... comme Détacher :)

Questions connexes