C# 如何更新一对多关系的父级和所有子级?
假设我有以下两个具有一对多关系的实体,其中一个报表可以有多个行项。这些实体最初是使用实体基础6代码创建的。C# 如何更新一对多关系的父级和所有子级?,c#,entity-framework,asp.net-mvc-5,one-to-many,entity-framework-6,C#,Entity Framework,Asp.net Mvc 5,One To Many,Entity Framework 6,假设我有以下两个具有一对多关系的实体,其中一个报表可以有多个行项。这些实体最初是使用实体基础6代码创建的。 public class Report { public int ID { get; set;} public DateTime ReportDate{ get; set;} public virtual ICollection<LineItems> LineItems { get; set;} } public class LineItems {
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;}
}
视图:
我需要能够在同一视图中更新单个报表及其所有相关行项目。可以有任意数量的行项目与单个报表关联。当我使用当前设置提交更新时,所有数据都已成功保存;但大多数子行项目的数据不正确。第一个子项是正确的,然后所有后续行项目都将使用第一行项目的数据而不是其各自输入的数据进行保存
我查看了页面生成的html源代码,所有LineItem输入都具有相同的id、名称等,格式为item_itemsdescription或item.itemsdescription。我很确定发生的事情是,因为它们都有相同的标识符,所以数据只是从具有这些标识符的页面上的第一个输入中提取出来的
那么,我如何指定哪个输入与哪个行项目一起使用呢?我觉得奇怪的是,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正确映射post数据,您必须将视图代码更改为:
...
@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);
}
...
[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();
...
}
}
...
@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);
}
...
...
[HttpPost]
public ActionResult Edit(Report raport)
{
if (ModelState.IsValid)
{
//do save stuff
}
}
...