1
resposta

[Bug] Crei o método para atualizar a musíca, ao atualizar o genero ocorre erro no EF

Boa tarde, tudo bem? como na aula temos o cadastrar, deletar, pensei em fazer o atualizar(editar), e meu teste seria incluir um novo gênero que ficou faltando (teste adicionar o gênero rock), Imagem da Tela de edição de músicaAo realizar a edição tive alguns problemas que estava duplicando ao salvar o novo gênero a musica, para corrigir o duplicar e reparei que só enviava o nome do gênero e não o Id, por falta do id do gênero ao salvar os gêneros antigos, eram inseridos novamente nas tabelas:

  • genero
  • generomusica

Mudança no GeneroRequestEdit

// antes:
    public record GeneroRequestEdit(string Nome, string Descricao)
    {
    }
// depois
    public record GeneroRequestEdit(int id, string Nome, string Descricao)
    {
    }

Assim evitei a duplicidade, porem gerou outro erro que não sei resolver: *SqlException: Violation of PRIMARY KEY constraint 'PKGeneroMusica'. Cannot insert duplicate key in object 'dbo.GeneroMusica'. The duplicate key value is (2, 11). The statement has been terminated. *

**Se é update pq ele esta tentando inserir um registro que já existe? Musica do exemplo e erro = 11 - Lady Laura

  • Tabela Musicas: Imagem da Tabela de Musicas

  • Tabela Gêneros: Imagem da tabela de gêneros

  • Tabela GeneroMusica Imagem Tabela GeneroMusica

**esse é meu método put **

            app.MapPut("/Musicas", ([FromServices] DAL<Musica> dal, [FromBody] Musica musica) =>
            {
                var musicaAAtualizar = dal.RecuperarPor(a => a.Id == musica.Id);
                if (musicaAAtualizar is null)
                {
                    return Results.NotFound();
                }

                // atualiza nome
                musicaAAtualizar.Nome = musica.Nome;
                // atualiza ano lancamento
                musicaAAtualizar.AnoLancamento = musica.AnoLancamento;
                // atualiza artista
                musicaAAtualizar.ArtistaId = musica.ArtistaId;
                musicaAAtualizar.Generos = musica.Generos.Select( a=> 
                        new Genero()
                        {
                            Id = a.Id,
                            Nome = a.Nome,
                            Descricao = a.Descricao,
                            Musicas = a.Musicas
                        }
                    ).ToList();

                dal.Atualizar(musicaAAtualizar);
                return Results.Ok();
            });
            #endregion

Na ultima tabela deveria apenas ser add (3, 11) e os outros (2,11),(5,11) apenas atualizar.

até posso fazer em meu put um filtro para manter só o que vier, de alteração, mas penso que o EF deveria saber como tratar um obj que tem listas, e ele mesmo atualizar... remover ou adiconar o que não esta em seu objeto virtual... (relacionado)

1 resposta

Olá, Marcelo.

Tudo bem?

O erro que você está enfrentando ocorre porque o Entity Framework está tentando inserir uma nova entrada na tabela GeneroMusica em vez de atualizar a existente. Isso geralmente acontece quando o Entity Framework não consegue rastrear corretamente as entidades relacionadas.

Para resolver esse problema, você precisa garantir que o Entity Framework saiba que os gêneros já existem e que a relação entre a música e os gêneros deve ser atualizada, não inserida. Aqui está uma abordagem para corrigir isso:

  1. Recupere os gêneros existentes da música antes de atualizar: Isso garante que o Entity Framework esteja ciente das entidades que já estão no banco de dados.

  2. Atualize a lista de gêneros: Em vez de criar novas instâncias de Genero, associe as existentes.

Aqui está um exemplo de como você pode modificar seu método PUT para fazer isso:

app.MapPut("/Musicas", ([FromServices] DAL<Musica> dal, [FromBody] Musica musica) =>
{
    var musicaAAtualizar = dal.RecuperarPor(a => a.Id == musica.Id);
    if (musicaAAtualizar is null)
    {
        return Results.NotFound();
    }

    // atualiza nome
    musicaAAtualizar.Nome = musica.Nome;
    // atualiza ano lancamento
    musicaAAtualizar.AnoLancamento = musica.AnoLancamento;
    // atualiza artista
    musicaAAtualizar.ArtistaId = musica.ArtistaId;

    // Recupera os gêneros existentes
    var generosExistentes = musicaAAtualizar.Generos.ToList();

    // Atualiza a lista de gêneros
    musicaAAtualizar.Generos.Clear();
    foreach (var genero in musica.Generos)
    {
        var generoExistente = generosExistentes.FirstOrDefault(g => g.Id == genero.Id);
        if (generoExistente != null)
        {
            // Atualiza as propriedades do gênero existente
            generoExistente.Nome = genero.Nome;
            generoExistente.Descricao = genero.Descricao;
            musicaAAtualizar.Generos.Add(generoExistente);
        }
        else
        {
            // Adiciona o novo gênero
            musicaAAtualizar.Generos.Add(genero);
        }
    }

    dal.Atualizar(musicaAAtualizar);
    return Results.Ok();
});

Neste código, estamos primeiro recuperando os gêneros existentes da música e, em seguida, limpando a lista de gêneros da música antes de adicionar os gêneros atualizados. Se o gênero já existir, apenas atualizamos suas propriedades; caso contrário, adicionamos o novo gênero.

Espero ter entendido e conseguido ajudar. Qualquer dúvida manda aqui. Bons estudos.