J'obtiens l'erreur suivante en essayant d'attacher un objet qui est déjà attaché à un contexte donné via context.AttachTo(...)
:
Un objet avec la même clé existe déjà dans ObjectStateManager. ObjectStateManager ne peut pas suivre plusieurs objets avec la même clé.
Existe-t-il un moyen de réaliser quelque chose du genre:
context.IsAttachedTo(...)
À votre santé!
Éditer:
La méthode d'extension décrite par Jason est proche, mais elle ne fonctionne pas pour ma situation.
J'essaie de faire du travail en utilisant la méthode décrite dans la réponse à une autre question:
Mon code ressemble un peu à ceci:
var user = new User() { Id = 1 };
context.AttachTo("Users", user);
comment.User = user;
context.SaveChanges();
Cela fonctionne bien, sauf lorsque je fais autre chose pour cet utilisateur où j'utilise la même méthode et j'essaye d'attacher un User
objet factice . Cela échoue car j'ai précédemment attaché cet objet utilisateur factice. Comment puis-je vérifier cela?
la source
(T)entry.Entity
retourne parfois null?T
c'est déjà le casIEntityWithKey
, ne pouvez-vous pas simplement utiliser saentity.EntityKey
propriété plutôt que de la reconstruire ou avoir besoin de deviner / fournir leEntitySetName
?Une approche plus simple est:
bool isDetached = context.Entry(user).State == EntityState.Detached; if (isDetached) context.Users.Attach(user);
la source
.Include()
les propriétés de navigation ed sont également tentées d'être attachées lorsque vous appelez.Attach
ou définissez sonEntityState
surEntityState.Unchanged
- et elles seront en conflit si l'une des entités fait référence au même entité. Je n'ai pas compris comment attacher uniquement l'entité de base, j'ai donc dû reconcevoir un peu le projet, pour utiliser des contextes séparés pour chaque "transaction commerciale", comme il a été conçu pour. Je vais le noter pour les projets futurs.Essayez cette méthode d'extension (elle n'est pas testée et prête à l'emploi):
public static bool IsAttachedTo(this ObjectContext context, object entity) { if(entity == null) { throw new ArgumentNullException("entity"); } ObjectStateEntry entry; if(context.ObjectStateManager.TryGetObjectStateEntry(entity, out entry)) { return (entry.State != EntityState.Detached); } return false; }
Compte tenu de la situation que vous décrivez dans votre modification, vous devrez peut-être utiliser la surcharge suivante qui accepte
EntityKey
un objet au lieu d'un objet:public static bool IsAttachedTo(this ObjectContext, EntityKey key) { if(key == null) { throw new ArgumentNullException("key"); } ObjectStateEntry entry; if(context.ObjectStateManager.TryGetObjectStateEntry(key, out entry)) { return (entry.State != EntityState.Detached); } return false; }
Pour créer un
EntityKey
dans votre situation, utilisez ce qui suit comme guide:EntityKey key = new EntityKey("MyEntities.User", "Id", 1);
Vous pouvez obtenir le à
EntityKey
partir d'une instance existante deUser
en utilisant la propriétéUser.EntityKey
(à partir de l'interfaceIEntityWithKey
).la source
TryGetObjectStateEntry
qui accepte unEntityKey
au lieu d'unobject
. J'ai modifié en conséquence. Faites-moi savoir si cela ne vous aide pas et nous reviendrons à la planche à dessin.À l'aide de la clé d'entité de l'objet que vous essayez de vérifier:
var entry = context.ObjectStateManager.GetObjectStateEntry("EntityKey"); if (entry.State == EntityState.Detached) { // Do Something }
La gentillesse,
Dan
la source
Cela ne répond pas directement à la question des OP mais c'est ainsi que j'ai résolu le mien.
Ceci est pour ceux qui utilisent à la
DbContext
place deObjectContext
.public TEntity Retrieve(object primaryKey) { return DbSet.Find(primaryKey); }
Méthode DbSet.Find :
Fondamentalement, il renvoie l'objet attaché du donné,
primaryKey
il vous suffit donc d'appliquer les modifications sur l'objet retourné pour conserver la bonne instance.la source