在一个编辑视图中编辑两个关联对象

时间:2014-11-04 14:44:11

标签: asp.net-mvc asp.net-mvc-4

我有几个这样的课程:

public class Widget
{
    public string WidgetId {get; set;)
    public Guid LocationId { get; set; }
    public virtual Location Location { get; set; }
}

public class Location
{
    public Guid LocationId { get; set; }
    public string Rack { get; set; }
    public string Bin { get; set; }
    public virtual ICollection<Widget> Widgets { get; set; }
}

在窗口小部件的编辑视图中,我允许用户编辑位置字段,以便:

@Html.HiddenFor(item => item.LocationId)
<div class="form-group">
    @Html.LabelFor(model => model.Location.Bin, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.Location.Bin, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.Location.Bin, "", new { @class = "text-danger" })
    </div>
</div>
<div class="form-group">
    @Html.LabelFor(model => model.Location.Rack, htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.EditorFor(model => model.Location.Rack, new { htmlAttributes = new { @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.Location.Rack, "", new { @class = "text-danger" })
    </div>
</div>

这是我的行动

public ActionResult Edit(string id)
{
    if (id == null)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
    }
    var widget = db.Widgets.Find(id);

    return View(widget);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "WidgetId,Location,LocationId")] Widget widget)
{
    if (ModelState.IsValid)
    {
        db.Widgets.Attach(widget);
        db.Locations.Attach(widget.Location);

        db.Entry(widget).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(widget);
}

在Widget的Edit POST处理程序中将编辑保存到两个对象的正确方法是什么?我试着保存Widget,但是我收到一条关于无法保存重复位置的错误。

1 个答案:

答案 0 :(得分:0)

如果你真的发布了你的行为会很有帮助,但根据你得到的错误,我可能会猜错。

当您向控制器操作发布内容时,模型绑定器会尝试将发布的内容绑定到操作接受的参数。在您的情况下,这可能是Widget的实例,也可能是WidgetLocation的实例。无论哪种方式,已经实例化的类看起来像类实体,因为您已经使用了您的实体类,但它们没有附加到您的实体框架上下文。因此,如果您尝试仅保存它们,Entity Framework会将它们视为全新对象,并尝试将它们保存为原样。由于您的位置具有ID,因此该ID将与现有对象的ID冲突,并且您会收到错误消息。要纠正此问题,您应该执行以下操作:

db.Locations.Attach(location);

或者

db.Entry(location).State = EntityState.Modified;

无论哪种方式,您的位置都将附加到上下文,然后将其视为更新而不是插入。

有关实体状态的详细信息,请参阅:Entity Framework Add/Attach and Entity States | MSDN