Je développe un projet d'API Web de base à des fins éducatives et j'ai des problèmes avec mes relations avec le modèle EF. J'ai 2 modèles. Message
et MessageBoard
.
[Route("api/[controller]")] [ApiController] public class MessageBoardsController : ControllerBase { private readonly MessageBoardContext _context; public MessageBoardsController(MessageBoardContext context) { _context = context; } // GET: api/MessageBoards/5 [HttpGet("{id}")] public async Task<ActionResult<MessageBoard>> GetMessageBoard(long id) { var messageBoard = await _context.MessageBoards.FindAsync(id); if (messageBoard == null) { return NotFound(); } return messageBoard; } // POST: api/MessageBoards [HttpPost] public async Task<ActionResult<MessageBoard>> PostMessageBoard(MessageBoard messageBoard) { _context.MessageBoards.Add(messageBoard); await _context.SaveChangesAsync(); return CreatedAtAction("GetMessageBoard", new { id = messageBoard.Id }, messageBoard); } } [Route("api/[controller]")] [ApiController] public class MessagesController : ControllerBase { private readonly MessageBoardContext _context; public MessagesController(MessageBoardContext context) { _context = context; } // GET: api/Messages/5 [HttpGet("{id}")] public async Task<ActionResult<Message>> GetMessage(long id) { var message = await _context.Messages.FindAsync(id); if (message == null) { return NotFound(); } return message; } // POST: api/Messages [HttpPost] public async Task<ActionResult<Message>> PostMessage(Message message) { _context.Messages.Add(message); await _context.SaveChangesAsync(); return CreatedAtAction("GetMessage", new { id = message.Id }, message); } }
J'ai configuré mon DBContext et créé une migration pour configurer la base de données. J'ai généré deux contrôleurs d'API Web à l'aide d'EF Scaffolding. La migration semble détecter correctement la relation entre les deux modèles:
{ "id": 2, "text": "Posting my first message!", "user": "Jesse", "postedDate": "2019-01-01T00:00:00", "messageBoardId": 4, "messageBoard": null }
Mais, lorsque je crée un MessageBoard puis que je crée un Message avec l'ID du MessageBoard, ils ne le font pas. t semblent se lier correctement. Dans PostMan, je fais ce qui suit:
1) Publier un nouveau MessageBoard
POST - https: // localhost: 44384 / api / MessageBoards /
Body - Raw - Json
{ "Text":"Posting my first message!", "User":"Jesse", "PostedDate":"1/1/2019", "MessageBoardId":4 }
Renvoie
{ "id": 4, "name": "Test Board", "description": "A Message board for testing purposes.", "messages": null }
2) Publier un nouveau message
POST - https: // localhost: 44384 / api / Messages
Body - Raw - JSON code>
{ "Name":"Test Board", "Description":"A Message board for testing purposes." }
Renvoie
modelBuilder.Entity("Asp.net_Core_Web_Api.Models.Message", b => { b.HasOne("Asp.net_Core_Web_Api.Models.MessageBoard", "MessageBoard") .WithMany("Messages") .HasForeignKey("MessageBoardId") .OnDelete(DeleteBehavior.Cascade); });
Je m'attendrais à ce que le messageBoard ne soit pas nul, et qu'il renvoie plutôt le JSON pour le messageBoard qui a été créé précédemment. Si je passe à une méthode GET, elle est également nulle. Pourquoi est-il nul?
EDIT: Voici mes contrôleurs. J'ai supprimé des actions à l'exception de GET et POST.
public class Message { public long Id { get; set; } public string Text { get; set; } public string User { get; set; } public DateTime PostedDate { get; set; } public long MessageBoardId { get; set; } [ForeignKey("MessageBoardId")] public MessageBoard MessageBoard { get; set; } } public class MessageBoard { public long Id { get; set; } public string Name { get; set; } public string Description { get; set; } public ICollection<Message> Messages { get; set; } }
3 Réponses :
Vous avez donné la sortie de l'application et à quoi ressemble la base de données, mais pas le bit du milieu sur la façon dont elle enregistre / récupère les données.
Sans savoir ce qui se passe au milieu, mon meilleur coup dans l'obscurité est que vous n'avez ni défini correctement votre chargement différé ni utilisé Inclure
pour inclure l'entité MessageBoard
. < / p>
Plus d'informations ici sur ce qu'ils sont .
Vous devez charger les données associées
Par exemple, pour votre MessageBoard
GET - // GET: api / MessageBoards / 5
Changer de:
var messageBoard = await _context.MessageBoards .Include(i=>i.Messages) .FirstOrDefaultAsync(i => i.Id == id);
À
var messageBoard = await _context.MessageBoards.FindAsync(id);
C'était ça. Je suis habitué à EF6 Database First où cela est automatiquement configuré, donc je n'ai pas pensé à le faire sur EF Core. J'ai tout mis à jour pour utiliser Eager Loading et cela a été corrigé. Je vous remercie!
@Jack pas de problème, veuillez marquer comme réponse si cela a aidé
J'attends juste que le chronomètre soit écoulé pour que je puisse le marquer :)
Je m'attendrais à ce que le messageBoard ne soit pas nul, et qu'il renvoie plutôt le JSON pour le messageBoard qui a été créé précédemment. Si je passe à une méthode GET, elle est également nulle. Pourquoi est-il nul?
Ceci est dû au fait que vous renvoyez le message nouvellement créé, ici seul
MessageBoadId
existe, pas l'objetMessageBoad
. Vous devez donc charger leMessageBoad
associé à partir de la base de données en utilisant Inclure pour le message nouvellement créé.Votre méthode
PostMessage
doit être la suivante:// POST: api/Messages [HttpPost] public async Task<ActionResult<Message>> PostMessage(Message message) { _context.Messages.Add(message); await _context.SaveChangesAsync(); var message = await _context.Messages .Include(i=>i.MessageBoard) .FirstOrDefaultAsync(i => i.Id == message.Id); return Json(message); }
Veuillez publier le code de vos méthodes d'action GET / PUT (où vous interrogez la base de données)
Sûr. Il est inchangé par rapport à l'échafaudage, donc je ne pensais pas que ce serait super utile. Une seconde. EDIT: ajouté.
@Jack Vérifiez votre question et ce que vous avez accepté comme réponse. Avez-vous posé la question correctement. Si c'est le cas, la réponse acceptée n'est certainement pas la solution exacte à votre question. Soit dit en passant, lisez ma réponse puis donnez votre avis.