135 votes

Entity Framework 4 - AddObject vs Attach

J'ai travaillé avec Entity Framework 4 récemment, et je suis un peu confus quant à savoir quand utiliser ObjectSet.Joindre, et ObjectSet.AddObject.

De ma compréhension:

  • L'utilisation "d'Attacher" lorsqu'une Entité existe déjà dans le système
  • Utiliser "AddObject" lors de la création d'une Entité nouvelle

Donc, si je suis en création d'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 suis à la modification d'une Personne, je fais ceci:

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

Gardez à l'esprit, c'est un très simple exemple. En réalité, je suis à l'aide de Pure POCO (pas de génération de code), un modèle de Référentiel (ne pas traiter avec des ctx.Personnes), et l'Unité de Travail (ne pas traiter avec des ctx.SaveChanges). Mais "sous les couvertures", le ci-dessus est ce qui se passe dans ma mise en œuvre.

Maintenant, ma question - je suis encore à trouver un scénario où j'ai eu à utiliser les Joindre.

Ce qui me manque ici? Quand faut-il utiliser Joindre?

MODIFIER

Juste pour préciser, je suis à la recherche d' exemples d'utilisation de Joindre plus de AddObject (ou vice-versa).

EDIT 2

Ci-dessous la réponse est correcte (j'ai accepté), mais j'ai pensé ajouter un autre exemple où Attacher serait utile.

Dans mon exemple ci-dessus pour la modification d'une Personne existante, deux requêtes sont effectivement en cours d'exécution.

De retrouver la Personne.SingleOrDefault), et un autre pour effectuer la mise à JOUR (.SaveChanges).

Si (pour certaines raisons), je savais déjà que "jean Dupont" existait dans le système, pourquoi faire une requête supplémentaire pour obtenir de lui la première? Je pourrais faire ceci:

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

Le résultat sera juste une mise à JOUR instruction en cours d'exécution.

166voto

Morteza Manavi Points 20486

ObjectContext.AddObject et ObjectSet.AddObject:
Le AddObject méthode est pour l'ajout de nouveaux objets qui ne sont pas dans la base de données. L'entité obtiendrez généré automatiquement temporaire EntityKey et de ses EntityState sera mis à Ajouté. Lorsque SaveChanges est appelé, il sera clair pour l'EF que cette entité doit être insérée dans la base de données.

ObjectContext.Joindre et ObjectSet.Joindre:
D'autre part, Attacher est utilisé pour les entités déjà exister dans la base de données. Plutôt que de définir la EntityState d'ajouter, Joindre les résultats dans un Inchangée EntityState, ce qui signifie qu'il n'a pas changé depuis qu'il a été attaché au contexte. Les objets que vous attachez sont supposés exister dans la base de données. Si vous modifiez les objets après qu'ils ont été attachés, lorsque vous appelez SaveChanges la valeur de la EntityKey est utilisé pour mettre à jour (ou supprimer) la ligne appropriée par trouver son ID correspondant dans la table db.

En outre, en utilisant la méthode de liaison, vous pouvez définir des relations entre les entités qui existent déjà dans le ObjectContext mais qui n'a pas été connecté automatiquement. Fondamentalement, le but principal de l'Attacher, est de relier les entités qui sont déjà attachés à la ObjectContext et sont pas de nouvelles de sorte que vous ne pouvez pas utiliser joindre pour Joindre les entités dont l'EntityState est Ajouté. Vous devez utiliser la méthode Add() dans ce cas.

Par exemple, supposons que votre Personne entité a une propriété de navigation nommé Adresses qui est une collection de l'Adresse de l'entité. Disons que vous avez lu les deux Objets à partir de leur contexte, mais ils ne sont pas liés les uns aux autres et vous souhaitez le faire donc:

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();

33voto

Tchi Yuan Points 742

C'est une réponse tardive, mais cela pourrait aider d'autres personnes à trouver cela.

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

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

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

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

C'est comme ça que je le comprends.

10voto

Teoman shipahi Points 7988

C'est une citation de Programmation Entity Framework: DbContext

L'appel de Supprimer sur une entité qui n'est pas suivi par le contexte qui va provoquer une exception InvalidOperationException à être jetés. L' Entity Framework génère cette exception, car il n'est pas clair de savoir si l'entité que vous tentez de supprimer est une entité existante qui doit être marqué pour suppression ou d'une nouvelle entité qui doivent être ignorés. Pour cette raison, nous ne pouvons pas utiliser tout simplement Supprimer pour marquer un déconnecté de l'entité comme étant Supprimés; nous avons besoin de l'Attacher en premier.

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();
    }
}

Le TestDeleteDestination méthode simule une application client extraction d'un existant Destination du serveur, puis en passant à la DeleteDestination méthode sur le serveur. Le DeleteDestination méthode utilise la méthode Attach de laisser le contexte sais que c'est une Destination existante. Ensuite, la suppression de la méthode est utilisée pour enregistrer l' de Destination existant pour la suppression

-8voto

Dan Points 27

Qu'en est-il de la référence à la clé primaire au lieu de l'attacher?

c'est à dire:

 var existingPerson = ctx.Persons.SingleOrDefault(p => p.Name = "Joe Bloggs" };
var myAddress = ctx.Addresses.First(a => a.PersonID != existingPerson.PersonID);
existingPerson.AddressId = myAddress.Id // not -> existingPerson.Addresses.Attach(myAddress);
// OR:
myAddress.Person.Id = existingPerson.Id // not -> myAddress.PersonReference.Attach(existingPerson);
ctx.SaveChanges();
 

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