theUser
theUser

Reputation: 1396

Foreign Key Field will not update upon Db.savechanges()

I have an incident model :

public class Incident
{
    public int Id { get; set; }
    public string Description { get; set; }
    public virtual Priority Priority { get; set; }
    public DateTime? ResolvedAt { get; set; }
}

and priority model :

public class Priority
{
    public int Id { get; set; }
    public string Description { get; set; }
}

which share a foreign key relationship. The Priority table has 10 fixed priorities from P0 to P9.

Here is the HttpPost after editing in the View.

    [HttpPost]
    public ActionResult Edit(Incident incident)
    {
        if (ModelState.IsValid)
        {
            if (incident.Id == 0)
                db.Incidents.Add(incident);
            else
            {
                db.Incidents.Attach(incident);
                db.Entry(incident).State = EntityState.Modified;
            }
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(incident);
    }

While debugging I can see everything updates inside the incident. But the changes are not reflected for the Priority after savechanges() (which has the foreign key relationship) Why is this ?

Upvotes: 0

Views: 962

Answers (1)

Slauma
Slauma

Reputation: 177133

Your procedure would work if you had an additional foreign key property public int PriorityId { get; set; } in the Incident model (or use int? as type if Incident.Priority is optional). You would then bind Incident.PriorityId to your view (a combobox?) instead of Incident.Priority.Id.

If you don't want a foreign key property and stick with your model as is the Edit action will be a bit more complex, like so:

[HttpPost]
public ActionResult Edit(Incident incident)
{
    if (ModelState.IsValid)
    {
        db.Priorities.Attach(incident.Priority);
        if (incident.Id == 0)
            db.Incidents.Add(incident);
        else
        {
            var incidentInDb = db.Incidents.Include(i => i.Priority)
                .SingleOrDefault(i => i.Id == incident.Id);
            if (incidentInDb != null)
            {
                db.Entry(incidentInDb).CurrentValues.SetValues(incident);
                incidentInDb.Priority = incident.Priority;
            }
        }
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(incident);
}

Generally setting the Modified state on an entity won't set this state for relationships (unless you have a foreign key property in your model, see first paragraph). That's the reason why your original code doesn't work and the additional line incidentInDb.Priority = incident.Priority is necessary. Change tracking will recognize if the priority did change and then update the foreign key in the database.

Upvotes: 1

Related Questions