Inquiridor
EF duplicando registros ao efetuar Updade de objeto

Pergunta
-
Olá,
Estou desenvolvendo um sistema web com MVC 5.
Para acesso a dados e persistência estou utilizando o EF6, mas estou com dificuldades para efetuar update (editar) um objeto com relacionamentos. No caso eu tenho um objeto Cliente que possui um Endereco. O problema é que quando tento editar um objeto cliente ele até salva a edição, mas também duplica tanto o Cliente quanto o Endereço.
Minhas classes POCO são:
public class Cliente { public Cliente() { Pesquisas = new HashSet<Pesquisa>(); } public int ClienteId { get; set; } public string NomeCliente { get; set; } public string TelCliente { get; set; } public Endereco EnderecoCliente { get; set; } public virtual ICollection<Pesquisa> Pesquisas { get; set; } } public class Endereco { public int EnderecoId { get; set; } public string CEP { get; set; } public string Cidade { get; set; } public string Bairro { get; set; } public string End { get; set; } public string Complemento { get; set; } public string UF { get; set; } [Required] public virtual Cliente Cliente { get; set; } }
Este é o método de alteração do Cliente (já tentei de várias outras formas):
public void AlterarClienteBL(Cliente _cliente) { PesquisaBL pesquisaBl = new PesquisaBL(); using (var banco = new SipomBD()) { int idCLiente = _cliente.ClienteId; Cliente clienteAlterar = banco.Clientes.Where(x => x.ClienteId == idCLiente).Single(); pesquisaBl.GenericDetach(clienteAlterar); clienteAlterar.NomeCliente = _cliente.NomeCliente; banco.SaveChanges(); } }
Em outras partes do projeto eu edito outros objetos e não há problemas, mas quando tento atualizar algum objeto Cliente ele sempre duplica tanto o cliente quanto o endereço do cliente, mesmo que não tenha sido feito alterações no endereço em si.
Alguém já passou por isso ou sabe a solução?
Desde já agradeço.
Todas as Respostas
-
Boa noite, mude seu método e deixe dessa forma...
public void AlterarClienteBL(Cliente _cliente) { PesquisaBL pesquisaBl = new PesquisaBL(); using (var banco = new SipomBD()) { banco.Entry(_cliente).State = System.Data.Entity.EntityState.Modified; banco.SaveChanges(); } }
-
Valeu a tentativa, Diego, mas ainda não deu certo.
Tentei da seguinte forma:
public void AlterarClienteBL(Cliente _cliente) { Cliente clienteAlterar = new Cliente(); clienteAlterar.ClienteId = _cliente.ClienteId; clienteAlterar.TelCliente = _cliente.TelCliente; clienteAlterar.NomeCliente = _cliente.NomeCliente; clienteAlterar.EnderecoCliente = new Endereco() { EnderecoId = _cliente.EnderecoCliente.EnderecoId, CEP = _cliente.EnderecoCliente.CEP, UF = _cliente.EnderecoCliente.UF, Cidade = _cliente.EnderecoCliente.Cidade, Bairro = _cliente.EnderecoCliente.Bairro, End = _cliente.EnderecoCliente.End, Complemento = _cliente.EnderecoCliente.Complemento }; using (var banco = new SipomBD()) { banco.Entry(clienteAlterar).State = EntityState.Modified; banco.SaveChanges(); } }
E deu o seguinte erro:
A referential integrity constraint violation occurred: The property value(s) of 'Cliente.ClienteId' on one end of a relationship do not match the property value(s) of 'Endereco.EnderecoId' on the other end.
Desconfio que meu código esteja com bad smell em algum outro lugar, só não sei ainda onde.
-
Winicius, provavelmente deu erro porque você criou um novo objeto cliente e tentou dar o status de modificado...faz assim:
Para alterar um objeto do EF que está no banco, com o id que deve ser atualizado, faça um select na base, retorne o cliente, altere os dados e com O MESMO OBJETO faça conforme te passei, posta o resultado aqui pra gente depois!!!
public void AlterarClienteBL(Cliente _cliente) { using (var banco = new SipomBD()) { //recupera o objeto do banco var clienteDb = banco.Clientes.FirstOrDefault(x=>x.ClienteId == _cliente.ClienteId); clienteDb.TelCliente = _cliente.TelCliente; clienteDb.NomeCliente = _cliente.NomeCliente; banco.Entry(clienteDb).State = EntityState.Modified; banco.SaveChanges(); } }
Faz esse teste...
- Editado Diego de Oliveira Neves terça-feira, 17 de novembro de 2015 23:15
- Sugerido como Resposta SimorC terça-feira, 17 de novembro de 2015 23:33
-
Winicius, provavelmente deu erro porque você criou um novo objeto cliente e tentou dar o status de modificado...faz assim:
Para alterar um objeto do EF que está no banco, com o id que deve ser atualizado, faça um select na base, retorne o cliente, altere os dados e com O MESMO OBJETO faça conforme te passei, posta o resultado aqui pra gente depois!!!
public void AlterarClienteBL(Cliente _cliente) { using (var banco = new SipomBD()) { //recupera o objeto do banco var clienteDb = banco.Clientes.FirstOrDefault(x=>x.ClienteId == _cliente.ClienteId); clienteDb.TelCliente = _cliente.TelCliente; clienteDb.NomeCliente = _cliente.NomeCliente; banco.Entry(clienteDb).State = EntityState.Modified; banco.SaveChanges(); } }
Faz esse teste...
Ou para facilitar:
var clienteDb = banco.Clientes.FirstOrDefault(x=>x.ClienteId == _cliente.ClienteId); banco.Entry(clienteDb).CurrentValues.SetValues(_cliente); banco.SaveChanges();
Att., Rafael Simor