Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update related entities in Entity Framework

I have an MVC project and using Entity Framework Code First and POCO objects for the database. For example:

public class ClassA
{
  public int? Id {get; set;}
  public string Name { get; set;}
  public virtual ClassB B {get; set;}
}

public class ClassB
{
  public int? Id {get;set;}
  public string Description {get;set;}
}

I have an ActionResult that create or edit a model. The problem is when I call this ActionResult to update the model, and model.B has been changed, the relation is not saved in the database. When the ActionResult is called to create a new object it works as expected. How do I solve this?

public ActionResult Save(ClassA model)
{
  model.B = GetBFromDb(model.B.Id.Value);

  if(ModelState.IsValid)
  {
    if (id.HasValue)
    {
      context.Entry(model).State = System.Data.EntityState.Modified;
    }
    else
    {
      context.ClassAs.Add(model);
    }
    context.SaveChanges();
    // redirect to index etc.
  }
  return View("EditForm", model);
}
like image 969
Marthijn Avatar asked Dec 08 '11 13:12

Marthijn


2 Answers

I solved it by changing ClassA with a foreign key to ClassB, and setting the value of BId:

public class ClassA
{
  public int? Id {get; set;}
  public string Name { get; set;}
  public int BId {get;set;} // foreign key to B
  public virtual ClassB B {get; set;}
}

Why does this foreign key property does the job instead of the generated foreign ky of EF?

like image 88
Marthijn Avatar answered Sep 17 '22 07:09

Marthijn


You can't simply call:

context.Entry(model).State = System.Data.EntityState.Modified;

The entity has to be retrieved from the context first so that EF can begin tracking it. Then you'll want to apply any changes to that entity before calling context.SaveChanges().

var entity = context.ClassAs.Find(model.Id);

// set properties you want to modify on entity
entity.Name = model.Name;
entity.ClassB = context.ClassBs.Find(model.ClassB.Id);
// other changes to entity as required...

context.SaveChanges();

This way EF is tracking entity and knows to apply an update against it.

like image 44
Yuck Avatar answered Sep 18 '22 07:09

Yuck