繁体   English   中英

如何更新一对多关系的父母和所有子女?

[英]How to update parent and all children of One-to-Many relationship?

假设我有以下两个具有一对多关系的实体,其中一个报表可以具有多个LineItem。 这些实体是使用Entity Foundation 6 Code First创建的。

public class Report
{
    public int ID { get; set;}
    public DateTime ReportDate{ get; set;}
    public virtual ICollection<LineItems> LineItems { get; set;}
}

public class LineItems
{
    public int ID { get; set;}
    public string ItemDescription{ get; set;}
    public virtual Report Report { get; set;}
}

我的控制器和视图中包含以下内容。

行动:

[HttpPost]
public ActionResult Edit(int? id)
{
    private CodeFirstContext context = new CodeFirstContext();
    ...
    Report rep = context.Reports.Include(x => x.LineItems).Single(x => x.ID == id);
    if(TryUpdateModel(rep, "", new string[] {"ReportDate"}))
    {
        foreach(var item in rep.LineItems)
        {
            if(TryUpdateModel(item, "item", new string[] {"ItemDescription"}))
            {
                context.LineItems.Attach(item);
                context.Entry(item).State = EntityState.Modified;
            }
        }
        context.Entry(rep).State = EntityState.Modified;
        context.SaveChanges();
        ...
    }
}

视图:

...
@Html.EditorFor(model => model.ReportDate);

@foreach (var item in Model.LineItems)
{
    @html.EditorFor(i => item.ItemDescription);
}
...

我需要能够在同一视图中更新单个Report及其所有相关LineItem。 单个报表可以有任意数量的LineItem。 当我使用当前设置提交更新时,所有数据都已成功保存; 但大多数子LineItems的数据不正确。 第一个孩子是正确的,然后所有后续LineItem与第一个LineItem中的数据一起保存,而不是与它们各自输入中的数据一起保存。

我查看了由页面生成的html源,所有LineItem输入具有相同的ID,名称等,形式为“ item_ItemDescription”或“ item.ItemDescription”。 我很确定发生的事情是因为它们都具有相同的标识符,所以数据只是从具有这些标识符的页面上的第一个输入中提取的。

那么如何指定哪个输入与哪个LineItem一起使用呢? 对我来说,奇怪的是,foreach语句并不会自动为其中的每个输入创建唯一的标识符。

解决了

正如py3r3str所建议的那样,我不得不更改视图以使用for循环而不是foreach并添加HiddenFor来保存每个实体的ID。 我必须更改模型才能使用:

public virtual IList<LineItems> LineItems {get; set;}

因为ICollection没有与其关联的索引。

我必须将控制器更改为:

[HttpPost]
public ActionResult Edit(Report report) //changed argument from id to Report
{
    private CodeFirstContext context = new CodeFirstContext();
    ...
    //following line unnecessary with new report argument
    //Report rep = context.Reports.Include(x => x.LineItems).Single(x => x.ID == id);
    if(TryUpdateModel(report, "", new string[] {"ReportDate"}))
    {
        for(int i = 0; i < report.LineItems.Count; i++) //change to for loop
        {
            if(TryUpdateModel(report.LineItems[i], "", new string[] {"ItemDescription"}))
            {
                //removed following line. Update does not work with it in there.
                //context.LineItems.Attach(report.LineItems[i]);
                context.Entry(report.LineItems[i]).State = EntityState.Modified;
            }
        }
        context.Entry(report).State = EntityState.Modified;
        context.SaveChanges();
        ...
    }
}

为了使MVC正确映射您的帖子数据,您必须将视图代码更改为:

...
@Html.HiddenFor(model => model.ID);
@Html.EditorFor(model => model.ReportDate);

@for (var i; i < Model.LineItems.Count; i++)
{
    @html.HiddenFor(e => Model.LineItems[i].ID);
    @html.EditorFor(e => Model.LineItems[i].ItemDescription);
}
...

然后,您的模型可以通过MVC控制器进行映射:

...
[HttpPost]
public ActionResult Edit(Report raport)
{
    if (ModelState.IsValid)
    {
        //do save stuff
    }
}
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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