Entity Framework 6, WCF e Detached Entities
Esse artigo irá ajudar outros programadores que estejam trabalhando com entity framework 6 em um cenário de inserção/alteração de entidades desatachadas.
Estou trabalhando em um sistema com o seguinte cenário:
Clients: Windows Forms e ASP NET MVC
Backend: WCF + EF6 + Azure Sql Database
No meu domínio, minhas entidades herdam desta BaseEntity abaixo:
public class BaseEntity { public DateTime DataCadastro { get; set; } public DateTime DataAlteracao { get; set; } public virtual OperadorSistema OperadorCadastro { get; set; } public virtual OperadorSistema OperadorAlteracao { get; set; } }
E estou tentando persistir a entidade Empresa:
public class Empresa : BaseEntity { public int EmpresaId { get; set; } }
Tendo apresentado o domínio, imaginem que na minha aplicação client, na tela de Edição de dados da Empresa, coleto os dados e envio para o método GravarEmpresa, no meu WCF.
No meu serviço, eu instancio um novo contexto do entity framework, e tento atachar a entidade recebida pelo WCF ao contexto:
this._dbSet.Attach(entity);
O cadastro da empresa chegou da seguinte forma:
Tenho um usuário “Admin” cadastrado, ao gravar alterações na “Empresa”, imaginem que tanto na propriedade OperadorCadastro quanto na OperadorAlteracao, o operador “Admin” está associado, com a mesma Primary Key, mas com referências de memória diferentes.
O entity framework faz um processamento sequencial atachando a entidade root, e as entidades associadas, e dispara o seguinte erro: “Attaching an entity of type failed because another entity of the same type already has the same primary key value.”
Para solucionar o erro, usei a biblioteca GraphDiff.
A biblioteca GraphDiff tem uma interface fluente, e facilita bastante o attach de objetos no contexto.
Conclusão:
=> Antes:
public override void Update(Empresa entity) { this.context.Empresas.Attach(entity); }
=> Depois:
public override void Update(Empresa entity) { context.UpdateGraph(entity, map => map.AssociatedEntity(ent => ent.OperadorAlteracao)); }
Referências:
Introduzindo biblioteca GraphDiff http://blog.brentmckendrick.com/introducing-graphdiff-for-entity-framework-code-first-allowing-automated-updates-of-a-graph-of-detached-entities/
Atachando entidade desconectada http://www.entityframeworktutorial.net/EntityFramework5/attach-disconnected-entity-graph.aspx