0

I think I have read every article and stack overflow question regarding this, but cannot work out the solution. Let me start out with my models

public class Entry
{
    public Entry ()
    {
        DateEntered = DateTime.Now;
    }

    public int Id { get; set; }
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    [Required]
    public string Email { get; set; }
    public string Number { get; set; }
    public string FbId { get; set; }
    [ReadOnly(true)]
    public DateTime DateEntered { get; set; }
    public string AccessToken { get; set; }

    //Relationsips
    public Backgrounds Background { get; set; }
    public Cars Car { get; set; }
}

public class Backgrounds
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Filename { get; set; }
}

public class Cars
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string FileName { get; set; }
}

Now in my controller, I am updating the entry. Like follows

    // PUT /api/entries/5
    public HttpResponseMessage Put(Entry entry)
    {
        if(ModelState.IsValid)
        {

            _db.Entries.Attach(entry);
            _db.Entry(entry).State = EntityState.Modified;
            _db.SaveChanges();

            return new HttpResponseMessage(HttpStatusCode.NoContent);
        }

        throw new HttpResponseException(HttpStatusCode.BadRequest);
    }

My Entry model gets updated correctly, but if for eg entry.Background.Name changes, this will not be persisted to the database. My controller is accepting the entire entry model including its relationships => Backgrounds and Cars. However any value that is changed to the relationship is not updated or reflected. Any elegant solution without having to query the database then updating? I dont want to have any extra queries or lookups before I update.

Thanks

Tyrone

TYRONEMICHAEL
  • 4,174
  • 4
  • 30
  • 47

1 Answers1

0

You must manually tell EF about all changes done to the object graph. You told EF just about change to entry instance but you didn't tell it about any change to related entities or relations itself. There is no elegant way to solve this. You have generally two options:

  • You will use some DTOs instead your entities and these DTOs will have some flag like IsDirty - when you receive object graph back to your controller you will reconstruct entities from DTOs and set their state based on IsDirty. This solution needs further extensions for example if your client can also delete relations.
  • You will query object graph from database and merge your incoming changes to entities retrieved from database.

There are some partial solutions like forcing to save changes to all related objects by setting their state to modified and identifying new objects by Id == 0 but again these solutions work only in specific scenarios.

More complex discussion about this problem.

Community
  • 1
  • 1
Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670