Я пытаюсь прикрепить Файл к Статья при сохранении моей статьи через веб-службу.
Вот как определяется мой Статья:
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.
Что мне не хватает?
@ZoharPeled, спасибо, но я не создаю файл при обновлении своей статьи. Я просто хочу прикрепить его.
Вы пробовали это? Вы говорите, что файл уже существует, верно? _dbContext.Entry(article.MailPictureFile).State = EntityState.Modified; И я полагаю, вы убедились, что он был правильно десериализован?
@ Тофер, видимо, сработало!! Пожалуйста, добавьте ответ, чтобы я мог его принять. Спасибо!
Вместо _dbContext.Entry(article).State = EntityState.Modified; используйте _dbContext.Update(article);
@IvanStoev, тоже работает. Большое Вам спасибо





Для полноты я попытаюсь объяснить больше, чем просто однострочный ответ.
Как вы подтвердили, использование _dbContext.Entry(article.MailPictureFile).State = EntityState.Modified; будет работать, потому что вы говорите DbContext начать отслеживать этот объект в Article.
Если бы вы извлекали этот объект Article из ef в смысле традиционного обновления, а не напрямую из вашего веб-сервиса, вам не нужно было бы сообщать Ef, чтобы он начал отслеживать его.
Другой способ избежать этого по ошибке — использовать концепцию DTO (объект передачи данных), который вы затем сопоставляете с объектом, который вы извлекли из своей базы данных, подобно концепции ViewModels, используемой в традиционном MVC. Таким образом, EF уже отслеживает его. Вы также получаете дополнительное преимущество проверок и использования ModelState таким образом.
Как говорит Иван Стоев в комментариях, использование _dbContext.Update(article); также будет работать. что лучше, потому что это одна строка вместо потенциальной строки для каждого подобъекта в соответствии с моим первоначальным предложением.
Здорово! Спасибо за объяснение
Это всего лишь догадка, но я думаю, что это связано с тем, что конструктор файлов предоставляет новый guid для каждого экземпляра класса File.