Why my One-To-Many field is not persisted in database

.net-core c# entity-framework-core

Question

I'm trying to attach a File to an Article when saving my Article though a Web Service.

Here is how my Article is defined:

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

    public File MainPictureFile
    {
        get; set;
    }

    (....)
}

The File Model is defined like that:

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

    public string Name
    {
        get; set;
    }

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

Here is how my Web Service is coded:

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

So I'm sending a JSON with a File already created before. I just want to attach it. Then I'm using a PUT Http request with a structure like this:

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

All others fields are working perfectly. Only the mainPictureFile is missing.

What am I missing?

1
0
3/1/2019 3:50:03 PM

Accepted Answer

For the sake of completeness I'm going to try explain more than just the one line answer.

As you've confirmed, using _dbContext.Entry(article.MailPictureFile).State = EntityState.Modified; will work, because you're telling the DbContext to start tracking that object within the Article.

If you were retrieving that Article object from ef in the sense of a traditional update and not from directly from your webservice you wouldn't have needed to tell Ef to start tracking it.

Another way to avoid this happening by mistake is using the concept of a DTO (data transfer object) which you then map to the object you you've retrieved from your database, like the concept of ViewModels used in traditional MVC. That way EF is already tracking it. You also get the added benefit of validations and using ModelState that way.

As Ivan Stoev says in the comments using _dbContext.Update(article); will also work. which is nicer because it's one line vs potentially a line per sub-object as per my original suggestion.

1
3/1/2019 4:27:04 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow