Почему мое поле One-To-Many не сохраняется в базе данных

Я пытаюсь прикрепить Файл к Статья при сохранении моей статьи через веб-службу.

Вот как определяется мой Статья:

public class Article : BaseEntity
{
    public string Title
    {
        get; set;
    }

    public File MainPictureFile
    {
        get; set;
    }

    (....)
}

Модель Файл определяется следующим образом:

public class File
{
    public Guid ID { get; set; }

    public string Name
    {
        get; set;
    }

    public File()
    {
        ID = Guid.NewGuid();
    }
}

Вот как закодирован мой веб-сервис:

[HttpPut]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(typeof(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary), StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesDefaultResponseType]
public async Task<ActionResult<Article>> PutArticle([FromBody] Article article)
{
    _dbContext.Entry(article).State = EntityState.Modified;
    try
    {
        await _dbContext.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException)
    {
        if (!ArticleExists(article.ID))
        {
            return NotFound();
        }
        {
            throw;
        }
    }
    return Ok(article);
}

Поэтому я отправляю JSON с уже созданным ранее Файл. Я просто хочу прикрепить его. Затем я использую запрос PUT Http с такой структурой:

{"id":"39e01ca9-f398-4359-8834-6a8e8400dfeb", "title":"Title", "mainPictureFile":{"id":"503047a3-4244-4299-bc18-1a42b564c2ed","name":"bat.jpg"},"position":0}

Все остальные поля работают отлично. Отсутствует только mainPictureFile.

Что мне не хватает?

Это всего лишь догадка, но я думаю, что это связано с тем, что конструктор файлов предоставляет новый guid для каждого экземпляра класса File.

Zohar Peled 01.03.2019 16:57

@ZoharPeled, спасибо, но я не создаю файл при обновлении своей статьи. Я просто хочу прикрепить его.

Kr1 01.03.2019 17:07

Вы пробовали это? Вы говорите, что файл уже существует, верно? _dbContext.Entry(article.MailPictureFile).State = EntityState.Modified; И я полагаю, вы убедились, что он был правильно десериализован?

Topher 01.03.2019 17:10

@ Тофер, видимо, сработало!! Пожалуйста, добавьте ответ, чтобы я мог его принять. Спасибо!

Kr1 01.03.2019 17:17

Вместо _dbContext.Entry(article).State = EntityState.Modified; используйте _dbContext.Update(article);

Ivan Stoev 01.03.2019 17:18

@IvanStoev, тоже работает. Большое Вам спасибо

Kr1 01.03.2019 17:22
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
40
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Для полноты я попытаюсь объяснить больше, чем просто однострочный ответ.

Как вы подтвердили, использование _dbContext.Entry(article.MailPictureFile).State = EntityState.Modified; будет работать, потому что вы говорите DbContext начать отслеживать этот объект в Article.

Если бы вы извлекали этот объект Article из ef в смысле традиционного обновления, а не напрямую из вашего веб-сервиса, вам не нужно было бы сообщать Ef, чтобы он начал отслеживать его.

Другой способ избежать этого по ошибке — использовать концепцию DTO (объект передачи данных), который вы затем сопоставляете с объектом, который вы извлекли из своей базы данных, подобно концепции ViewModels, используемой в традиционном MVC. Таким образом, EF уже отслеживает его. Вы также получаете дополнительное преимущество проверок и использования ModelState таким образом.

Как говорит Иван Стоев в комментариях, использование _dbContext.Update(article); также будет работать. что лучше, потому что это одна строка вместо потенциальной строки для каждого подобъекта в соответствии с моим первоначальным предложением.

Здорово! Спасибо за объяснение

Kr1 01.03.2019 17:28

Другие вопросы по теме