I’m new to MVC and Entity frame work but i’ve come across an issue and i’m not sure how to resolve it some guidance is more then welcome. I’m editing an object which has a sub list of different objects. I’ve got a working edit screen but i cant get the details stored back the database. I think the issue is around the context of the db but as i said i’m new to this. Here are the 2 classes i’m using:
public class Role
{
[Key]
public string Role { get; set; }
public virtual ICollection<Template> Templates { get; set; }
}
public class Template
{
[Key][Required]
public string TemplateID { get; set; }
[Required]
public string Header { get; set; }
[Required][DataType(DataType.MultilineText)]
public string Description { get; set; }
public virtual ICollection<CorrespondenceRole> Roles { get; set; }
}
I also have this in my context
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Template>()
.HasMany(c => c.Roles)
.WithMany(c => c.Templates)
.Map(m => m.ToTable("Template_Roles")
.MapLeftKey("TemplateID")
.MapRightKey("Role"));
}
If i use
public ActionResult Edit(Template ctemplate)
{
db.Entry(ctemplate).State = EntityState.Modified;
db.SaveChanges();
}
The changes to the template object are recorded to the database but any changes to the roles list are totally ignored even if i hardcode ctemplate.roles.add(somerole) before the db save.
However if i use
public ActionResult Edit(Template ctemplate)
{
Template ct = db.Templates.Find(ctemplate.TemplateID);
ct.Roles.Add(db.Roles.Find("Other Party"));
db.Entry(ct).State = EntityState.Modified;
db.SaveChanges();
}
The “role” is saved against in the template in the database. So i could use this code to find the object then copy all the form fields into it and save it but it seems long winded when the first option does actually work but it just does not save my list. Any comments or suggestions how best to save the changes to the object and its associated list of different objects? Thanks.
UPDATE
I found this worked for me, but i have no idea if its the best way to go about it.
db.Entry(ct).State = EntityState.Modified;
foreach (var entity in db.Roles.Where(cr => cr.TemplateID == ct.ID))
db.Roles.Remove(entity);
foreach (Role cr in ct.Roles)
db.Roles.Add(cr);
db.SaveChanges();
There’s not a fast way that I’m aware of. When you fetch your Template from the database, you want to load the associated roles as well (look up Eager Loading); that’s not related to your problem but will save you on db round-trips.
Once your Roles are loaded by the context, you’ll have to iterate over them and modify whatever’s changed and add new ones and delete the old ones. It’s manual, but it ensures that the datacontext knows what you want changed on the objects.
After that, calling save on the template should trickle down to the roles.