2

Here is the situation, i have three entities of which has the following relationships:

-Team one-to-one TeamContact
-TeamContact one-to-one TeamAddress

I have managed to create, add and save these objects with no trouble. However, when i tried to create an edit method, only the parent object is being saved after modifications. See below what i have so far;

Save method in my Db class

public void SaveTeam(Team team)
    {
        if (team.Id == 0)
        {
            context.Teams.Add(team);
        }
        else
        {
            var model = context.Teams.Find(team.Id);
            context.Entry(model).CurrentValues.SetValues(team);
        }
        context.SaveChanges();
    }

Edit Method

[HttpGet]
    public ActionResult Edit(int id)
    {
        var model = _dataSource.Teams.FirstOrDefault(t => t.Id == id);
        return View(model);
    }

    [HttpPost]
    public ActionResult Edit(Team team)
    {
        if (ModelState.IsValid)
        {
            _dataSource.SaveTeam(team);

            return RedirectToAction("Detail", "Team", new { id = team.Id });
        }
        return View(team);
    }

Like i said above, what i have only lets me modify the parent object, what have i missed here?

Tried

 public void SaveTeam(Team team)
    {
        if (team.Id == 0)
        {
            context.Teams.Add(team);
        }
        else
        {
            //var model = context.Teams.Find(team.Id);
            var model = context.Teams.Include(c => c.TeamContact).Single(t => t.Id == team.Id);
            context.Entry(model).CurrentValues.SetValues(team);
            model.TeamContact = team.TeamContact;
        }
        context.SaveChanges();
    }

I got this error after trying the above:

Violation of PRIMARY KEY constraint 'PK_dbo.TeamAddresses'. Cannot insert duplicate key     in object 'dbo.TeamAddresses'. The duplicate key value is (5).
 The statement has been terminated.

Bottom line, how does one update N-Level deep objects?

Komengem
  • 3,662
  • 7
  • 33
  • 57

2 Answers2

5

After a long search and readings, I finally figured what I was intending to do. I was lucky creating and saving N-Level deep object graph wasn't as hard as Updating those Objects. Anyways, after reading Danny Varod's comment, I decide to go back and read more on DbContext. Below is what I was trying to do, also I apologize I am using the same method to save new objects:

public void SaveTeam(Team team)
    {
        if (team.Id == 0)
        {
            context.Teams.Add(team);
        }
        else if (team.Id > 0)
        {
            //This Updates N-Level deep Object grapgh
            var currentTeam = context.Teams
                .Include(c => c.TeamContact)
                .Include(a => a.TeamContact.TeamAddress)
                .Single(t => t.Id == team.Id);

            context.Entry(currentTeam).CurrentValues.SetValues(team);
            currentTeam.TeamContact.TeamAddress = team.TeamContact.TeamAddress;
            currentTeam.TeamContact = team.TeamContact;
        }
        context.SaveChanges();
    }
Thomas Sobieck
  • 1,416
  • 1
  • 20
  • 27
Komengem
  • 3,662
  • 7
  • 33
  • 57
  • Just a point of clarification. The commented line does not update the objects. Rather, it loads them from the database and registers them with the context. It is the registering that causes EF to realize they've changed and update them accordingly. – Katie Kilian Jun 29 '16 at 20:56
2

Unlike the add, which attaches the entire graph which is reachable from the provided entity, the apply changes only applies changes to the provided entity, it does not know which connected entities should be modified too.

You will have to call apply changes for each entity.

Danny Varod
  • 17,324
  • 5
  • 69
  • 111
  • Thanks, please take a look above and see what i just tried. Also it could help if you provided an example with your explanation. – Komengem Dec 06 '12 at 09:18