Aparentemente fazendo o debugging ele a lógica está correta, mas apesar dele voltar um 201 e retornar o dado no método Post, quando eu executo o método Get ele volta nulo, porque a nota não foi persistida.
Post:
Get:
Aparentemente fazendo o debugging ele a lógica está correta, mas apesar dele voltar um 201 e retornar o dado no método Post, quando eu executo o método Get ele volta nulo, porque a nota não foi persistida.
Post:
Get:
Avaliação:
using ScreenSound.Modelos;
namespace ScreenSound.Shared.Models.Models;
public class AvaliacaoArtista
{
public virtual Artista? Artista { get; set; }
public int ArtistaId { get; set; }
public int PessoaId { get; set; }
public int Nota { get; set; }
}
Artista:
public string Nome { get; set; }
public string FotoPerfil { get; set; }
public string Bio { get; set; }
public int Id { get; set; }
public virtual ICollection<Musica> Musicas { get; set; } = new List<Musica>();
public virtual ICollection<AvaliacaoArtista> Avaliacoes { get; set; } = new List<AvaliacaoArtista>();
...
public void AdicionarNota(int pessoaId, int nota)
{
nota = Math.Clamp(nota, 1, 5); // Garante que a nota esteja entre 1 e 5
Avaliacoes.Add(new AvaliacaoArtista() { ArtistaId = this.Id, PessoaId = pessoaId, Nota = nota });
}
Request:
namespace ScreenSound.API.Requests;
public record AvaliacaoArtistaRequest(int ArtistaId, int Nota);
Response:
using System.ComponentModel.DataAnnotations;
namespace ScreenSound.API.Responses;
public record AvaliacaoArtistaResponse([Required] int ArtistaId, [Required] int Nota);
Program:
builder.Services.AddTransient<DAL<PessoaComAcesso>>();
Endpoint:
// Rota que permite avaliar um artista
groupBuilder.MapPost("avaliacao", (HttpContext context, [FromBody] AvaliacaoArtistaRequest request, [FromServices] DAL<Artista> dalArtista, [FromServices] DAL<PessoaComAcesso> dalPessoaComAcesso) =>
{
var artista = dalArtista.FindBy(a => a.Id == request.ArtistaId);
if (artista is null) return Results.NotFound();
// O ?? é um operador de coalescência nula, que retorna o valor da esquerda se não for nulo, senão o valor da direita
var email = context.User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Email)?.Value
?? throw new InvalidOperationException("Usuário não autenticado");
// Se o email não for encontrado, lança uma exceção de InvalidOperationException com a mensagem "Pessoa não encontrada"
var pessoa = dalPessoaComAcesso.FindBy(p => p.Email == email)
?? throw new InvalidOperationException("Pessoa não encontrada");
// Verifica se a pessoa já avaliou o artista, passando o id do artista e o id da pessoa
var avaliacao = artista.Avaliacoes.FirstOrDefault(a => a.ArtistaId == artista.Id && a.PessoaId == pessoa.Id);
// Se a avaliação não existir, adiciona a nota
if (avaliacao is null)
{
// Adiciona a nota
artista.AdicionarNota(pessoa.Id, request.Nota);
}
else
{
// Se a avaliação existir, atualiza a nota
dalArtista.Atualizar(artista);
}
return Results.Created();
});
// Rota que busca a nota do artista
groupBuilder.MapGet("{id}/avaliacao", (int id, HttpContext context, [FromServices] DAL<Artista> dalArtista, [FromServices] DAL<PessoaComAcesso> dalPessoa) =>
{
// Valida se o artista existe
var artista = dalArtista.FindBy(a => a.Id == id);
if (artista is null) return Results.NotFound();
// Verifica se a pessoa está autenticada
var email = context.User.Claims.FirstOrDefault(c => c.Type.Equals(ClaimTypes.Email))?.Value
?? throw new InvalidOperationException("Não foi encontrado o email da pessoa logada");
// Verifica se a pessoa existe
var pessoa = dalPessoa.FindBy(p => p.Email!.Equals(email))
?? throw new InvalidOperationException("Não foi encontrado o email da pessoa logada");
// Busca a avaliação do artista feita pela pessoa, passando o id do artista e o id da pessoa
var avaliacao = artista.Avaliacoes.FirstOrDefault(a => a.ArtistaId == id && a.PessoaId == pessoa.Id);
// Se a avaliação não existir, retorna 0
if (avaliacao is null)
{
// Retorna a nota 0
return Results.Ok(new AvaliacaoArtistaResponse(id, 0));
}
else
{
// Se a avaliação existir, retorna a nota
return Results.Ok(new AvaliacaoArtistaResponse(id, avaliacao.Nota));
}
});
Consegui fazer ele persistir o dado no banco, tinha colocado o método atualizar dento do if, mas na verdade ele é fora, pois é ele quem vai persistir meu dado no banco.
Trecho do código do endpoint:
groupBuilder.MapPost...
// Se a avaliação não existir, adiciona a nota
if (avaliacao is null)
{
// Adiciona a nota
artista.AdicionarNota(pessoa.Id, request.Nota);
}
else
{
// Se a avaliação existir, atualiza a nota
avaliacao.Nota = request.Nota;
}
// Se a avaliação existir, atualiza a nota
dalArtista.Atualizar(artista);
return Results.Created();
});
Agora eu estou com um erro que ele não consegue ir lá no meu DB e voltar o dado pra mim. E por conta disso ele está dando erro, porque ele acha que não tem nada e tenta adicionar novamente um dado que já existe.
Verificando o código, tando no Post quando no Get, o trecho que está com problema é onde ele faz a verificação da avaliação, porque está voltando null.
// Verifica se a pessoa já avaliou o artista, passando o id do artista e o id da pessoa
var avaliacao = artista.Avaliacoes.FirstOrDefault(a => a.ArtistaId == artista.Id && a.PessoaId == pessoa.Id);
Essa abordagem seria meio que uma solução para continuar o curso, mas não é bem o foco. Porque o objetivo é popular a coleção de Avaliações em Artistas.
Solução temporária:
var avaliacao = artista.Avaliacoes.FirstOrDefault(a => a.ArtistaId == id && a.PessoaId == pessoa.Id);
var dalAvaliacao = dalAvaliacaoArtista.FindBy(av => av.ArtistaId == id && av.PessoaId == pessoa.Id);
avaliacao = dalAvaliacao;
De fato a "solução" que eu encontrei ajuda a gravar no banco de dados. Mas essa gambiarra não me dá muitos benefícios, porque eu preciso que a lista em Artista seja populada e eu não estou conseguindo um retorno satisfatório com essa gambiarra, para que a classificação me retorne a média das notas.
Segue o meu github, para ajudar a visualizar o código.
https://github.com/IgorTudisco/Entity-Framework-Core/tree/main/ScreenSound.API
Oi, Igor! Tudo bem?
O problema pode estar na forma como você está carregando os dados do banco. O EF Core, por padrão, não carrega relacionamentos automaticamente. Você precisa garantir que a lista de avaliações está sendo carregada corretamente quando você busca o artista.
Ajuste a consulta para incluir as avaliações usando Include:
var artista = dalArtista
.FindBy(a => a.Id == id)
.Include(a => a.Avaliacoes);
Se você estiver usando um repositório genérico, talvez seja necessário modificar o método FindBy para permitir Includings. Agora, se o problema persistir, verifique se o banco realmente tem os dados persistidos. Rode um SELECT diretamente no banco para conferir.
Espero ter ajudado e bons estudos!