Estou recebendo o seguinte erro ao tentar anexar um objeto que já está anexado a um determinado contexto por meio de context.AttachTo(...)
:
Já existe um objeto com a mesma chave no ObjectStateManager. O ObjectStateManager não pode rastrear vários objetos com a mesma chave.
Existe uma maneira de alcançar algo nos moldes de:
context.IsAttachedTo(...)
Felicidades!
Editar:
O método de extensão descrito por Jason está próximo, mas não funciona na minha situação.
Estou tentando fazer algum trabalho usando o método descrito na resposta a outra pergunta:
Meu código se parece um pouco com este:
var user = new User() { Id = 1 };
context.AttachTo("Users", user);
comment.User = user;
context.SaveChanges();
Isso funciona bem, exceto quando eu faço outra coisa para aquele usuário em que uso o mesmo método e tento anexar um User
objeto fictício . Isso falha porque eu anexei anteriormente esse objeto de usuário fictício. Como posso verificar isso?
fonte
(T)entry.Entity
às vezes retorna nulo?T
já estiverIEntityWithKey
, você não pode simplesmente usar suaentity.EntityKey
propriedade em vez de reconstruí-la ou precisar adivinhar / fornecer oEntitySetName
?Uma abordagem mais simples é:
bool isDetached = context.Entry(user).State == EntityState.Detached; if (isDetached) context.Users.Attach(user);
fonte
.Include()
as propriedades de navegação 'ed também tentam ser anexadas quando você chama.Attach
ou as defineEntityState
comoEntityState.Unchanged
- e elas entrarão em conflito se qualquer uma das entidades se referir ao mesma entidade. Não descobri como anexar apenas a entidade base, então tive que redesenhar um pouco o projeto, para usar contextos separados para cada "transação comercial", como foi projetado. Vou anotar isso para projetos futuros.Experimente este método de extensão (não testado e improvisado):
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; }
Dada a situação que você descreve em sua edição, pode ser necessário usar a seguinte sobrecarga que aceita um em
EntityKey
vez de um objeto: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; }
Para construir um
EntityKey
em sua situação, use o seguinte como diretriz:EntityKey key = new EntityKey("MyEntities.User", "Id", 1);
Você pode obter o
EntityKey
de uma instância existente deUser
usando a propriedadeUser.EntityKey
(da interfaceIEntityWithKey
).fonte
TryGetObjectStateEntry
que aceita um emEntityKey
vez de umobject
. Eu editei em conformidade. Avise-me se isso não ajudar e voltaremos à prancheta.Usando a chave de entidade do objeto que você está tentando verificar:
var entry = context.ObjectStateManager.GetObjectStateEntry("EntityKey"); if (entry.State == EntityState.Detached) { // Do Something }
Bondade,
Dan
fonte
Isso não responde diretamente à pergunta dos OPs, mas foi assim que resolvi a minha.
Isso é para aqueles que estão usando em
DbContext
vez deObjectContext
.public TEntity Retrieve(object primaryKey) { return DbSet.Find(primaryKey); }
Método DbSet.Find :
Basicamente, ele retorna o objeto anexado do dado,
primaryKey
então você só precisa aplicar as alterações no objeto retornado para manter a instância correta.fonte