将多个实体插入到多对多链接表中
我的Web应用程序在Station
和Timetable
实体之间具有多对多链接,并且链接它们的实体称为StationTimetable
,它还保存有关两个实体之间链接的数据。 当我创建一个新的Timetable
,我想在数据库中创建新的(和多个) StationTimetable
条目以对应这个新的Timetable
。
到目前为止,我已经设法让应用程序在用户创建新的时间表时只保存一个StationTimetable
条目。 我有点理解为什么会这样,并且我试图修改它以保存多个条目,但是我现在正在知道这个砖墙。
所以,我有一个TimetablesCreateViewModel
,它是我的视图使用的模型:
public class TimetablesCreateViewModel { public Timetable Timetable { get; set; } public IEnumerable StationTimetables { get; set; } public Station Station { get; set; } public SelectList StationList { get; set; } }
在我看来,我让用户最多插入10个StationTimetable
条目:
@for (var i = 0; i < 10; i++) { @Html.DropDownListFor(model => model.StationTimetables.StationId, Model.StationList, "---", htmlAttributes: new { @class = "form-control col-md-2" }) @Html.EditorFor(model => model.StationTimetables.Arrival, new { htmlAttributes = new { @class = "form-control" } }) @Html.EditorFor(model => model.StationTimetables.Departure, new { htmlAttributes = new { @class = "form-control" } }) }
然后,在我的控制器方法中,我想做类似以下的事情:
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); }
直接的问题似乎是我的视图中的DropDownListFor
和EditorFor
方法都在抱怨,这是有道理的,因为我已经在我的视图模型中指定了StationTimetables
为IEnumerable
,并且我无法访问StationId
, Arrival
和Departure
属性IEnumerable
。 这些属性是IEnumerable
持有的实体的一部分。
不幸的是,我不知道如何使用Html
帮助器来创建一个表单,我可以使用许多StationTimetable
实体填充StationTimetables
。 如果我可以在我的Create
方法中获得多个StationTimetable
条目,那么我认为在此之后将它们添加到数据库中会有问题。
感谢您的任何帮助。
您需要使您的StationTimetables
属性IList
并使用索引器,以便正确命名属性并可以在回发后绑定
@for (var i = 0; i < 10; i++) { @Html.DropDownListFor(m => m.StationTimetables[i].StationId, Model.StationList, "---", htmlAttributes: new { @class = "form-control col-md-2" }) @Html.EditorFor(m => m.StationTimetables[i].Arrival, new { htmlAttributes = new { @class = "form-control" } }) @Html.EditorFor(m => m.StationTimetables[i].Departure, new { htmlAttributes = new { @class = "form-control" } }) }
例如,这将生成正确的名称属性
如果您无法从IEnumerable
更改它,则可以为typeof StationTimetable
创建自定义EditorTemplate
查看/共享/ EditorTemplates / StationTimetable.cshtml
@model YourAssembly.StationTimetable @Html.DropDownListFor(m => m.StationId, (SelectList)ViewData["StationList"], "---", new { @class = "form-control col-md-2" }) @Html.EditorFor(m => m.Arrival, new { htmlAttributes = new { @class = "form-control" } }) @Html.EditorFor(m => m.Departure, new { htmlAttributes = new { @class = "form-control" } })
然后在主视图中
@EditorFor(m => m.StationTimetables, new { StationList = Model.Model.StationList })
此方法意味着在将模型传递给视图之前,需要在控制器中初始化包含10个项目的StationTimetables
属性。
在任何情况下,我推荐使用EditorFor()
方法,因为在for
循环中使用DropDownListFor()
出现了一个bug(已报告但尚未解决)。
但是我怀疑你并没有真正总是有10个站时间表( 我让用户插入最多 10个 )这使得这种方法不灵活 – 例如,如果你向属性添加validation属性,模型将无效,除非所有填写了10个时间表属性。最好使用javascript或BeginCollectionItem帮助程序动态添加新的时间表。 这个答案中包含了这两种方法的一个例子