简体   繁体   中英

C# MVC saving a list of sub items

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();

This worked for a similar problem for me !!

foreach (var entity in db.Roles.Where(cr => cr.TemplateID == ct.ID)) {
                db.Entry(entity).State = EntityState.Modified;
            }

db.Roles.Remove(entity);  

Are the objects present in ctemplate in the save procedure? In your view are you also doing this:

foreach (var item in model.sub_object)
{
  @Html.TextBoxFor(m => item.whatever)
}

Try something like this:

for (int i; i < model.sub_object.count(); i++)
{
  @Html.TextBoxFor(m => model.sub_object[i].field)
}

If your problem is what I think it is, this will solve it. The problem is that you need to change the EntityState of each element on your lists. Try this:

public ActionResult Edit(Template ctemplate)
{
    db.Entry(ctemplate).State = EntityState.Modified;
    foreach (CorrespondenceRole role in ctemplate.Roles)
    {
        //Change role State -> EntityState.Modified
    }   
    db.SaveChanges();
}

If your elements are attached to your context, they should persist to the database... Let me know if you have any question...

Hope this helps.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM