【问题标题】:Inserting multiple entities into many-to-many linking table将多个实体插入多对多链接表
【发布时间】:2015-01-20 14:12:25
【问题描述】:

我的 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 指定为IEnumerable,我可以'不要访问IEnumerableStationIdArrivalDeparture 属性。这些属性是IEnumerable 持有的实体的一部分。

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

感谢您的帮助。

【问题讨论】:

  • TimetableStation 类中是否还有其他导航属性?关于抱怨 Html 助手,也许我会在访问属性之前使用StationTimetables.ToList()

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


【解决方案1】:

您需要将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 更改它,您可以为 typeof StationTimetable 创建一个自定义 EditorTemplate

Views/Shared/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() 方法,因为在for 循环中使用DropDownListFor() 时存在错误(已报告但尚未解决)。

但是我怀疑你并不总是有 10 个站点的时间表(我让用户插入 up 到 10)这使得这种方法不灵活 - 因为例如,如果您为属性添加验证属性,则除非填写所有 10 个时间表属性,否则模型将无效。最好使用 javascript 或 BeginCollectionItem 助手动态添加新的时间表。 this answer

中包含了这两种方法的示例

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-05
    • 2023-01-03
    • 2011-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    相关资源
    最近更新 更多