ASP.NET Core Web API и EF Core Модели с отношением внешнего ключа - PullRequest
0 голосов
/ 08 февраля 2019

Я занимаюсь разработкой базового проекта Web API для образовательных целей, и у меня возникли проблемы с моими отношениями в EF Model.У меня есть 2 модели.Message и MessageBoard.

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

Я настроил DBContext и создал миграцию для настройки базы данных.Я сгенерировал два контроллера Web API, используя EF Scaffolding.Миграция, по-видимому, правильно определяет отношения между двумя моделями:

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

Но, когда я создаю MessageBoard, а затем создаю сообщение с идентификатором MessageBoard, они, кажется, не связываются правильно.В PostMan я делаю следующее:

1) Опубликовать новую доску объявлений

POST - https://localhost:44384/api/MessageBoards/

Body - Raw - Json

{
 "Name":"Test Board",
 "Description":"A Message board for testing purposes."
}

Returns

{
    "id": 4,
    "name": "Test Board",
    "description": "A Message board for testing purposes.",
    "messages": null
}

2) Опубликовать новое сообщение

POST - https://localhost:44384/api/Messages

Body - Raw - JSON

{
    "Text":"Posting my first message!",
    "User":"Jesse",
    "PostedDate":"1/1/2019",

    "MessageBoardId":4
}

Возвраты

{
    "id": 2,
    "text": "Posting my first message!",
    "user": "Jesse",
    "postedDate": "2019-01-01T00:00:00",
    "messageBoardId": 4,
    "messageBoard": null
}

Я ожидал бы, что messageBoard не будет нулевым, и вместо этого он вернет JSON для messageBoard, который был ранее создан.Если я перехожу на метод GET, он также является нулевым.Почему это ноль?

РЕДАКТИРОВАТЬ: Вот мои контроллеры.Я удалил действия за исключением GET и POST.

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

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

Вам необходимо загрузить связанные данные

Так, например, для вашего MessageBoard GET - // GET: api/MessageBoards/5

Изменить с:

var messageBoard = await _context.MessageBoards.FindAsync(id);

К

var messageBoard = await _context.MessageBoards
                        .Include(i=>i.Messages)
                        .FirstOrDefaultAsync(i => i.Id == id);
0 голосов
/ 08 февраля 2019

Я ожидал бы, что messageBoard не будет нулевым, и вместо этого он вернет JSON для messageBoard, который был ранее создан.Если я перехожу на метод GET, он также является нулевым.Почему оно пустое?

Это потому, что вы возвращаете только что созданное сообщение, здесь существует только MessageBoadId, а не MessageBoad объект.Поэтому вам нужно загрузить связанный MessageBoad из базы данных, используя Включить для вновь созданного сообщения.

Ваш PostMessage метод должен быть следующим:

// 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);
}
0 голосов
/ 08 февраля 2019

Вы указали выходные данные приложения и то, как выглядит база данных, но не средний бит о том, как она сохраняет / получает данные.Не зная, что происходит в середине, мой лучший удар в темноте заключается в том, что вы ни правильно установили свою ленивую загрузку, ни не использовали Include для включения MessageBoard сущности.

Подробнее здесь о том, что они есть.

...