none
EF duplicando registros ao efetuar Updade de objeto RRS feed

  • 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.

      

    segunda-feira, 16 de novembro de 2015 23:01

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

    segunda-feira, 16 de novembro de 2015 23:16
  • 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.

    terça-feira, 17 de novembro de 2015 22: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...


    • 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
    terça-feira, 17 de novembro de 2015 23:15
  • 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

    terça-feira, 17 de novembro de 2015 23:35