web-dev-qa-db-fra.com

Entity Framework 4 - AddObject vs Attach

Je travaille avec Entity Framework 4 récemment et je suis un peu confus quant au moment d'utiliser ObjectSet.Attach , et ObjectSet.AddObject .

D'après ce que j'ai compris:

  • Utilisez "Attacher" lorsqu'une entité existe déjà dans le système
  • Utilisez "AddObject" lors de la création d'une nouvelle entité.

Donc, si je crée une nouvelle personne , je le fais.

var ctx = new MyEntities();
var newPerson = new Person { Name = "Joe Bloggs" };
ctx.Persons.AddObject(newPerson);
ctx.SaveChanges();

Si je modifie une personne existante , je le fais:

var ctx = new MyEntities();
var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
existingPerson.Name = "Joe Briggs";
ctx.SaveChanges();

N'oubliez pas qu'il s'agit d'un exemple très simple . En réalité, j'utilise Pure POCO (sans génération de code), un modèle de référentiel (ne traite pas de ctx.Persons) et d'unité de travail (ne traite pas de ctx.SaveChanges). Mais "sous les couvertures", ce qui précède est ce qui se passe dans ma mise en œuvre.

Maintenant, ma question - Je n'ai pas encore trouvé de scénario où j'ai dû utiliser Joindre .

Qu'est-ce que j'oublie ici? Quand devons-nous utiliser Attach?

[~ # ~] éditer [~ # ~]

Juste pour clarifier, je cherche exemples quand utiliser Attach via AddObject (ou vice-versa).

EDIT 2

La réponse ci-dessous est correcte (ce que j’ai accepté), mais je pensais ajouter un autre exemple où Attach serait utile.

Dans mon exemple ci-dessus pour modifier une personne existante , deux requêtes sont en cours d'exécution.

Un pour récupérer la personne (.SingleOrDefault) et un autre pour exécuter UPDATE (.SaveChanges).

Si (pour une raison quelconque), je savais déjà que "Joe Bloggs" existait dans le système, pourquoi faire une requête supplémentaire pour l'obtenir en premier? Je pourrais faire ceci:

var ctx = new MyEntities();
var existingPerson = new Person { Name = "Joe Bloggs" };
ctx.Persons.Attach(existingPerson);
ctx.SaveChanges();

Cela entraînera simplement l'exécution d'une instruction UPDATE.

127
RPM1984

ObjectContext.AddObject et ObjectSet.AddObject:
La méthode AddObject sert à ajouter des objets nouvellement créés qui font pas existe dans la base de données. L'entité obtiendra un temporaire EntityKey généré automatiquement et son EntityState sera défini sur Ajouté. Lorsque SaveChanges est appelé, il est clair pour le FE que cette entité doit être insérée dans la base de données.

ObjectContext.Attach et ObjectSet.Attach :
D'autre part, Attach est utilisé pour les entités qui ont déjà exist dans la base de données. Plutôt que de définir EntityState sur Added, Attachez les résultats dans un Inchanged EntityState, ce qui signifie qu'il n'a pas changé depuis son rattachement au contexte. Les objets que vous attachez sont supposés exister dans la base de données. Si vous modifiez les objets après leur attachement, lorsque vous appelez SaveChanges, la valeur de EntityKey est utilisée pour mettre à jour (ou supprimer) la ligne appropriée en recherchant son ID correspondant dans la table de base de données.

De plus, en utilisant la méthode Attach, vous pouvez définir des relations entre des entités qui existent déjà dans ObjectContext mais qui ont pas été connecté automatiquement. Fondamentalement, l'objectif principal de Attach est de connecter des entités déjà attachées à ObjectContext et pas new. Vous ne pouvez donc pas utiliser Attacher pour attacher des entités dont EntityState est ajouté. Vous devez utiliser Ajouter () dans ce cas.

Par exemple, supposons que votre entité Personne possède une propriété de navigation nommée Adresses, qui est une collection de Adresse. Supposons que vous avez lu les deux objets dans leur contexte, mais qu'ils ne sont pas liés et que vous voulez le rendre ainsi:

var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID);
existingPerson.Addresses.Attach(myAddress);
// OR:
myAddress.PersonReference.Attach(existingPerson)
ctx.SaveChanges();
158
Morteza Manavi

C'est une réponse tardive, mais cela pourrait aider les autres qui le trouvent.

Fondamentalement, une entité "déconnectée" peut se produire lorsque vous manipulez une entité en dehors de la portée "using".

Employee e = null;

using (var ctx = new MyModelContainer())
{
     e = ctx.Employees.SingleOrDefault(emp => emp .....);
}

using (var ctx2 = new MyModelContainer())
{
     e; // This entity instance is disconnected from ctx2
}

Si vous entrez une autre portée "using", la variable "e" sera déconnectée car elle appartient à la portée précédente "using" et, étant donné que la précédente portée "using" est détruite, "e" est déconnecté.

C'est comme ça que je le comprends.

28
TchiYuan

Ceci est une citation de Programming Entity Framework: DbContext

L’appel de suppression sur une entité non suivie par le contexte provoquera la génération d’une exception InvalidOperationException. Entity Framework lève cette exception car il n’est pas clair si l’entité que vous essayez de supprimer est une entité existante qui doit être marquée pour suppression ou une nouvelle entité qui doit simplement être ignorée. Pour cette raison, , nous ne pouvons pas utiliser simplement Supprimer pour marquer une entité déconnectée comme étant supprimée; nous devons d'abord l'attacher .

private static void TestDeleteDestination()
{
    Destination canyon;
    using (var context = new BreakAwayContext())
    {
        canyon = (from d in context.Destinations
        where d.Name == "Grand Canyon"
        select d).Single();
    }
    DeleteDestination(canyon);
}
private static void DeleteDestination(Destination destination)
{
    using (var context = new BreakAwayContext())
    {
        context.Destinations.Attach(destination);
        context.Destinations.Remove(destination);
        context.SaveChanges();
    }
}

La méthode TestDeleteDestination simule une application cliente récupérant une destination existante du serveur, puis la transmettant à la méthode DeleteDestination sur le serveur. La méthode DeleteDestination utilise la méthode Attach pour indiquer au contexte qu’il s’agit d’une destination existante. Ensuite, la méthode Remove est utilisée pour enregistrer la destination existante en vue de sa suppression.

7
Teoman shipahi