将多个实体插入到多对多链接表中

时间:2015-01-20 14:12:26

标签: c# asp.net-mvc entity-framework many-to-many asp.net-mvc-viewmodel

我的Web应用程序在StationTimetable实体之间有多对多链接,链接它们的实体称为StationTimetable,它还包含有关链接的数据两个实体之间。当我创建新的Timetable时,我想在数据库中创建新的(和多个)StationTimetable条目以对应这个新的Timetable

到目前为止,当用户创建新的时间表时,我设法让应用程序只保存一个StationTimetable条目。我有点理解为什么会这样,而且我试图修改它以保存多个条目,但是我现在正在知道这个砖墙。

所以,我有一个TimetablesCreateViewModel,这是我的视图使用的模型:

public class TimetablesCreateViewModel
{
    public Timetable Timetable { get; set; }

    public IEnumerable<StationTimetable> StationTimetables { get; set; }

    public Station Station { get; set; }

    public SelectList StationList { get; set; }
}

在我看来,我让用户最多插入10个StationTimetable条目:

@for (var i = 0; i < 10; i++)
{
    <tr>
        <td>@Html.DropDownListFor(model => model.StationTimetables.StationId, Model.StationList, "---", htmlAttributes: new { @class = "form-control col-md-2" })</td>
        <td>@Html.EditorFor(model => model.StationTimetables.Arrival, new { htmlAttributes = new { @class = "form-control" } })</td>
        <td>@Html.EditorFor(model => model.StationTimetables.Departure, new { htmlAttributes = new { @class = "form-control" } })</td>
    </tr>
}

然后,在我的控制器方法中,我想做类似以下的事情:

public ActionResult Create(TimetablesCreateViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        db.Timetables.Add(viewModel.Timetable);

        // Somehow loop over viewModel.StationTimetables and add them here?
        // db.StationTimetables.Add(viewModel.StationTimetable);

        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(viewModel);
}

直接问题似乎是我的视图中的DropDownListForEditorFor方法都在抱怨,这是有意义的,因为我在视图模型中指定StationTimetables为{ {1}},我无法访问IEnumerable的{​​{1}},StationIdArrival属性。这些属性是Departure持有的实体的一部分。

不幸的是,我不知道如何使用IEnumerable帮助程序创建一个表单,我可以使用多个IEnumerable实体填充Html。如果我可以在我的StationTimetables方法中获得多个StationTimetable条目,那么我认为在此之后将它们添加到数据库中会有问题。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您需要创建StationTimetables属性IList并使用索引器,以便正确命名属性并在回发后绑定

@for (var i = 0; i < 10; i++)
{
  <tr>
    <td>@Html.DropDownListFor(m => m.StationTimetables[i].StationId, Model.StationList, "---", htmlAttributes: new { @class = "form-control col-md-2" })</td>
    <td>@Html.EditorFor(m => m.StationTimetables[i].Arrival, new { htmlAttributes = new { @class = "form-control" } })</td>
    <td>@Html.EditorFor(m => m.StationTimetables[i].Departure, new { htmlAttributes = new { @class = "form-control" } })</td>
  </tr>
}

这将生成正确的名称属性,例如

<input name="StationTimetables[0].StationId" ...>
<input name="StationTimetables[1].StationId" ...>

如果您无法从IEnumerable更改,则可以为EditorTemplate

类型创建自定义StationTimetable

查看/共享/ EditorTemplates / StationTimetable.cshtml

@model YourAssembly.StationTimetable
<tr>
  <td>@Html.DropDownListFor(m => m.StationId, (SelectList)ViewData["StationList"], "---", new { @class = "form-control col-md-2" })</td>
  <td>@Html.EditorFor(m => m.Arrival, new { htmlAttributes = new { @class = "form-control" } })</td>
  <td>@Html.EditorFor(m => m.Departure, new { htmlAttributes = new { @class = "form-control" } })</td>
</tr>

然后在主视图中

@EditorFor(m => m.StationTimetables, new { StationList = Model.Model.StationList })

这种方法意味着在将模型传递给视图之前,需要在控制器中初始化具有10个项目的StationTimetables属性。

在任何情况下,由于在EditorFor()循环中使用DropDownListFor()的错误(已报告但尚未解决),我建议您使用for方法。

但是我怀疑你并不总是有10个电台时间表(我让用户插入向上到10 )方法不灵活 - 例如,如果您向属性添加验证属性,除非填写所有10个时间表属性,否则模型将无效。最好使用javascript或BeginCollectionItem帮助程序动态添加新的时间表。这两种方法的示例都包含在this answer